///////////////////////////////////////////// // ENBSeries effect file // // visit http://enbdev.com for updates // // Copyright (c) 2007-2011 Boris Vorontsov // // ENBSeries Modifications 2.0.5 by Matso // // Modifed by Michael Tichenor (IndigoNeko)// ///////////////////////////////////////////// float EDirectionalBlurMultiplier=3.0; // NOTE: This file is formatted to be viewed in Courier New font, at size 8. ///////////////////////// // DEFINES AND ENABLES // ///////////////////////// // NOTE: To activate a feature, remove the two slashes in front of the #define. To deactivate it, add two slashes. #define ENABLE_FAST_DOF // Enable Modified version of Matso's Fast DoF // #define USE_FAST_DOF_CHROMA // Use Chromatic Aberration in Depth of Field #define USE_FAST_DOF_BOKEH // Use Depth of Field Bokeh effects. // #define ENABLE_CHROMA // Enable Chromatic Aberration (in addition to that applied in the Fast DoF). //////////////////////////////////////////////////////////////////////// // I've implemented two new experimental Depth of Field effects here. // // Both are based on real camera aperture equations, and use f-stop // // values for determining aperture size. The first is the Simple DoF // // and the second is a Sprite DoF. Both allow in-game control of the // // aperture size. DO NOT USE MULTIPLE DOFS AT THE SAME TIME. Enjoy! // // ~IndigoNeko // //////////////////////////////////////////////////////////////////////// // NOTE: Hold 0 + PG UP or PG DN to adjust camera aperture (f-stop) for Simple and Sprite DoF. // #define ENABLE_SMART_APERTURE // Enable Smart Aperture Control for Simple and Sprite DoF (automatic f-stop adjustment). // #define ENABLE_SIMPLE_DOF // Enable Simple Depth of Field. Not quite as good looking as Matso's Fast DoF, but more realistic. // WARNING: SPRITE DOF RENDERS A SPRITE AT EVERY PIXEL. THAT'S 2 MILLION SPRITES AT 1080p! EXTREMELY SLOW! MAY CAUSE CRASHES! // NOTE: The alpha channel of enbpalette.bmp is used to store Bokeh shapes for the Sprite DoF. // #define ENABLE_SPRITE_DOF // Enable Sprite Depth of Field. // #define USE_SPRITE_HACK // Use a hack to speed up Sprite DoF rendering. ///////////////////////////////////////////////////////////////////////// // In addition to the experimental Depth of Field, I've implemented a // // series of different focus detection algorithms. They allow you to // // control a little more precisely how the focus for Depth of Field is // // determined. Only use ONE focusing method for the focus system. // // ~IndigoNeko // ///////////////////////////////////////////////////////////////////////// // NOTE: Hold 9 + PG UP or PG DN to adjust manual camera focus distance in-game. #define ENABLE_FOCUS_SYSTEM // Enable focus detection system. See Focus System Settings for details. // #define USE_FOCUS_MANUAL // Use preset to focus to the exact distance specified. // #define USE_FOCUS_FARTHEST // Use preset to focus on farthest of all points sampled. // #define USE_FOCUS_AVERAGE // Use preset to focus on average of all points sampled. #define USE_FOCUS_NEAREST // Use preset to focus on nearest of all points sampled. //#define USE_FOCUS_FIRST // Use intelligent focusing system for First person mode. // #define USE_FOCUS_THIRD // Use Intelligent focusing system for Third person mode. ////////////////////////// // GLOBALS AND SETTINGS // ////////////////////////// // Chromatic Aberration settings. float3 fChromaDisplacement = float3(0.995, 1.000, 1.005); // Controls displacement scales of red, green and blue respectively. float fChromaBaseRadius = 0.9; // Controls aberration radius. Anything below this radius, the effect is less visible.. float fChromaFalloffRadius = 1.8; // Controls aberration radius. Anything over this radius, the effects is maximal. float fChromaPower = 1.0; // Controls power of the chromatic displacement (curve of the 'fChromaDisplacement' vector). // Fast Depth of Field settings. float fFastApertureScale = 0.12; // Controls image blur scale (the bigger value, the stronger blur). Default: 0.12. float fFastApertureCutoff = 1.0; // Controls the smoothness of the DoF (bigger value results in wider depth of field). Default: 1.0. float fFastApertureBias = 0.0; // Controls the distance not taken into account in DoF. Default: 0.0 float fFastApertureMaxBlur = 16.0; // Controls the maximum amount of blur that can be applied. Default: 20.0 float fFastApertureMaxFocus = 3.0; // Controls the maximum focus distance in meters for fast DoF. Default: 3.0. //float fFastBokehCurve = 2.0; // Controls bokeh curve. The larger the value, the more visible the bokeh effect is. Default: 3.0. //CHANGED FOR MORE CONTRASTED BOKEH float fFastBokehCurve = 8.0; // Controls bokeh curve. The larger the value, the more visible the bokeh effect is. Default: 3.0. float fFastBokehLight = 1.5; // Controls overall brightness of bokeh blurred areas. Default: 1.1. // Simple and Sprite Depth of Field settings. float fCameraFocalLength = 50.0; // Controls the distance from lens to sensor plane, in millimeters. float fApertureDefault = 12.0; // Controls the default camera aperture. float fApertureSmartMult = 4.0; // Controls camera aperture: f-stop = ( focus distance * this multiplier ). float fApertureSmartMax = 48.0; // Controls the maximum aperture f-stop when smart focusing float fApertureSmartMin = 2.0; // Controls the minimum aperture f-stop value for smart focusing. float fBokehMult = 10.0; // Controls the bokeh multiplier. float fBokehCurve = 2.0; // Controls the bokeh curve. float fSimpleDoFMaxBlur = 16.0; // UGLY HACK TO LIMIT BLURRING FOR SIMPLE DOF. float2 fBokehSpriteMax = float2( 16.0, 16.0 ); // Controls the maximum Bokeh sprite size. float2 fBokehSpriteMin = float2( 1.0, 1.0 ); // Controls the minimum Bokeh sprite size. // Focus System settings. float fFocusSystemLOD = 1.0; // Controls the mipmapping LOD of radial focus detection. Currently useless. float fFocusSystemMin = 0.0; // Controls the minumum focus distance in meters. Default: 0.5. float fFocusSystemMax = 20.0; // Controls the maximum focus distance in meters. Default: 20.0. float fFocusSystemBias = 0.0; // Controls an offset to the focus distance in meters. Default: 1.0. float fFocusSystemMult = 1.0; // Controls a multiplier to the focus distance. Default: 0.0. // Focus System Manual Preset settings. float fFocusManualDistance = 5.0; // Controls the focus distance from the camera in meters. // Focus System Farthest Preset settings. float fFocusFarthestMaximum = 5.0; // If using farthest focus, set focus at most this many meters from camera. float fFocusFarthestMinimum = 1.0; // If using farthest focus, set focus at least this many meters from camera. float2 fFocusFarthestCenter = float2( 0.5, 0.5 ); // Specifies center coordinate (in screen coordinates). float2 fFocusFarthestRange = float2( 0.25, 0.25 ); // Sets the horizontal and vertical sample range. float2 fFocusFarthestSampleRate = float2( 0.05, 0.05 ); // Sets the offset between samples. Range: 0.01 to fFocusFarthestWindow/2 // Focus System Average Preset settings. float fFocusAverageMaximum = 5.0; // If using average focus, set focus at most this many meters from camera. float fFocusAverageMinimum = 1.0; // If using average focus, set focus at least this many meters from camera. float2 fFocusAverageCenter = float2( 0.5, 0.5 ); // Sets the center coordinate (in screen coordinates). float2 fFocusAverageRange = float2( 0.25, 0.25 ); // Sets the horizontal and vertical sample range. float2 fFocusAverageSampleRate = float2( 0.02, 0.02 ); // Sets the offset between samples. Range: 0.01 to fFocusAverageWindow/2 // Focus System Nearest Preset settings. float fFocusNearestMaximum = 5.0; // If using nearest focus, set focus at most this many meters from camera. float fFocusNearestMinimum = 1.0; // If using nearest focus, set focus at least this many meters from camera. float2 fFocusNearestCenter = float2( 0.5, 0.5 ); // Sets the center coordinate (in screen coordinates). float2 fFocusNearestRange = float2( 0.25, 0.25 ); // Sets the horizontal and vertical sample range. float2 fFocusNearestSampleRate = float2( 0.05, 0.05 ); // Sets the offset between samples. Range: 0.01 to fFocusAverageWindow/2 // Focus System 1st Person Preset settings. float4 fFocusSmart1stWindow = float4( 0.35, 0.45, 0.65, 0.55 ); // Sets the window in screen coordinates ( left, top, right, bottom ). float4 fFocusSmart1stReticule = float4( 0.45, 0.45, 0.55, 0.525 ); // Sets the reticule in screen coordinates ( left, top, right, bottom ). float2 fFocusSmart1stSampleRate = float2( 0.02, 0.02 ); // Sets the offset between samples. Range: 0.01 to fFocusAverageWindow/2 float fFocusSmart1stCutoffWindow = 2.5; // If object in window is less than this many meters away, ignore it. float fFocusSmart1stCutoffReticule = 1.0; // If object in reticule is less than this many meters away, ignore it (unless it's in crosshairs). float fFocusSmart1stSpeed = 0.25; // Sets the speed of lens focusing, in seconds. // Focus System 3rd Person Preset settings. float4 fFocusSmart3rdWindow = float4( 0.35, 0.45, 0.52, 0.54 ); // Specifies the window in screen coordinates ( left, top, right, bottom ). float2 fFocusSmart3rdSampleRate = float2( 0.05, 0.05 ); // Specifies offset between samples. Range: 0.01 to fFocusAverageWindow/2 float fFocusSmart3rdCutoffMax = 5.0; // If object in crosshairs is more than this many meters away, look for something nearby to focus on. float fFocusSmart3rdCutoffMin = 0.7; // If object in crosshairs is less than this many meters away, look at it regardless of closer objects. float fFocusSmart3rdSpeed = 2.0; // Sets the speed of lens focusing, in seconds. ////////////////////////////////////////////// // DO NOT MODIFY ANYTHING BELOW THIS LINE, // // UNLESS YOU KNOW HLSL SHADER PROGRAMMING. // ////////////////////////////////////////////// // Keyboard controlled temporary variables. Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0 float4 tempF1; //0,1,2,3 float4 tempF2; //5,6,7,8 float4 tempF3; //9,0 float4 ScreenSize; // x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY float4 Timer; // x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds) float FadeFactor; // Adaptation delta time for focusing // Matso's Constants // Useful constants #define PI 3.1415926535897932384626433832795 #define CHROMA_POW 10.0 // the bigger the value, the more visible chomatic aberration effect in DoF // Fast DoF constants #define DOF_SCALE 2356.1944901923449288469825374596 // PI * 750 #define FIRST_PASS 2 // DO NOT CHANGE THIS. #define SECOND_PASS 3 // DO NOT CHANGE THIS. #define THIRD_PASS 0 // DO NOT CHANGE THIS. #define FOURTH_PASS 1 // DO NOT CHANGE THIS. #define DOF(sd,sf) fFastApertureScale * smoothstep(fFastApertureBias, fFastApertureCutoff, abs(sd - sf)) ////////////// // TEXTURES // ////////////// texture2D texColor; texture2D texDepth; texture2D texNoise; texture2D texPalette; texture2D texFocus; texture2D texCurr; texture2D texPrev; sampler2D SamplerColor = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; AddressU = Mirror; AddressV = Mirror; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerDepth = sampler_state { Texture = ; MinFilter = POINT; MagFilter = POINT; MipFilter = NONE; AddressU = Clamp; AddressV = Clamp; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerNoise = sampler_state { Texture = ; MinFilter = POINT; MagFilter = POINT; MipFilter = NONE; AddressU = Wrap; AddressV = Wrap; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerPalette = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; AddressU = Clamp; AddressV = Clamp; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerCurr = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; AddressU = Clamp; AddressV = Clamp; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerPrev = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; AddressU = Clamp; AddressV = Clamp; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; sampler2D SamplerFocus = sampler_state { Texture = ; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = NONE; AddressU = Clamp; AddressV = Clamp; SRGBTexture = FALSE; MaxMipLevel = 0; MipMapLodBias = 0; }; ///////////// // STRUCTS // ///////////// struct VS_OUTPUT_POST { float4 vpos : POSITION; float2 txcoord : TEXCOORD0; }; struct VS_INPUT_POST { float3 pos : POSITION; float2 txcoord : TEXCOORD0; }; /////////////// // FUNCTIONS // /////////////// // Convert depth buffer values to a distance in meters. float DepthToDistance( float Depth ) { if( Depth < 1.0 && Depth >= 0.0 ) { return min( 10000.0, ( 0.15 / ( 1.0 - Depth ) ) ); } return 10000.0; } // Convert distance in meters to depth buffer values. float DistanceToDepth( float Distance ) { if( Distance > 0.0 ) { return saturate( 1.0 - ( 0.15 / Distance ) ); } return 0.0; } // Calculate diameter of Circle of Confusion in millimeters from object and focus distance. float CircleofConfusion( float FocusDistance, float ObjectDistance ) { float fAperture = fApertureDefault; #ifdef ENABLE_SMART_APERTURE fAperture = clamp( FocusDistance * fApertureSmartMult, fApertureSmartMin, fApertureSmartMax ); #endif // Circle of Confusion equation from WikiPedia. float A = fCameraFocalLength / ( fAperture * max( 0.01, tempF3.y ) ); float S1 = FocusDistance; float S2 = ObjectDistance; float C = A * abs( S2 - S1 ) / S2; return C; } // IEC 61966-2-1 sRGB Specification for Luminance. float Luminance( float3 Color ) { float3 sRGB = float3( 0.2125, 0.7154, 0.0721 ); return dot( Color, sRGB ); } /*------------------------------------------------------------------------------ ENB prepass modification 2.0.5 by Matso Credits to Boris Vorontsov ------------------------------------------------------------------------------*/ /** * Chromatic aberration function - given texture coordinate and a focus value * retrieves chromatically distorted color of the pixel. Each of the color * channels are displaced according to the pixel coordinate and its distance * from the center of the image. Also the DoF out-of-focus value is applied. * (http://en.wikipedia.org/wiki/Chromatic_aberration) */ float4 ChromaticAberration(float2 tex, float outOfFocus) { float d = distance(tex, float2(0.5, 0.5)); float f = smoothstep(fChromaBaseRadius, fChromaFalloffRadius, d + outOfFocus * d); float3 chroma = pow(f + fChromaDisplacement, fChromaPower); float2 tr = ((2.0 * tex - 1.0) * chroma.r) * 0.5 + 0.5; float2 tg = ((2.0 * tex - 1.0) * chroma.g) * 0.5 + 0.5; float2 tb = ((2.0 * tex - 1.0) * chroma.b) * 0.5 + 0.5; float3 color = float3(tex2D(SamplerColor, tr).r, tex2D(SamplerColor, tg).g, tex2D(SamplerColor, tb).b) * (1.0 - f); return float4(color, 1.0); } /** * Chromatic aberration done accoriding to the focus factor provided. */ float4 ChromaticAberrationFocus(float2 tex, float outOfFocus) { float3 chroma = pow(fChromaDisplacement, CHROMA_POW * outOfFocus); float2 tr = ((2.0 * tex - 1.0) * chroma.r) * 0.5 + 0.5; float2 tg = ((2.0 * tex - 1.0) * chroma.g) * 0.5 + 0.5; float2 tb = ((2.0 * tex - 1.0) * chroma.b) * 0.5 + 0.5; float3 color = float3(tex2D(SamplerColor, tr).r, tex2D(SamplerColor, tg).g, tex2D(SamplerColor, tb).b) * (1.0 - outOfFocus); return float4(color, 1.0); } /** * Converts pixel color to gray-scale. */ float GrayScale(float3 sample) { return dot(sample, float3(0.3, 0.59, 0.11)); } ///////////// // SHADERS // ///////////// VS_OUTPUT_POST VS_Focus(VS_INPUT_POST IN) { VS_OUTPUT_POST OUT; float4 pos = float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0); OUT.vpos = pos; OUT.txcoord.xy = IN.txcoord.xy; return OUT; } float4 PS_ReadFocus(VS_OUTPUT_POST IN) : COLOR { float res = tex2D( SamplerDepth, 0.5 ).x; // Enables Focusing System #ifdef ENABLE_FOCUS_SYSTEM // Manual Focusing #ifdef USE_FOCUS_MANUAL res = DistanceToDepth( fFocusManualDistance * max(0.01, tempF3.x) ); #endif // Farthest Focusing #ifdef USE_FOCUS_FARTHEST float2 uvcenter = saturate( fFocusFarthestCenter ); float2 uvrange = saturate( fFocusFarthestRange ); float2 uvstart = saturate( uvcenter - ( uvrange * 0.5 ) ); float2 uvfinish = saturate( uvcenter + ( uvrange * 0.5 ) ); float2 uvrate = min( ( uvrange * 0.5 ), fFocusFarthestSampleRate ); for( float u = uvstart.x; u <= uvfinish.x; u += uvrate.x ) { for( float v = uvstart.y; v <= uvfinish.y; v += uvrate.y ) { float4 uv = float4( u, v, 0.0, fFocusSystemLOD ); float depth = tex2Dlod( SamplerDepth, uv ).x; res = max( res, depth ); } } #endif // Average Focusing #ifdef USE_FOCUS_AVERAGE float2 uvcenter = saturate( fFocusAverageCenter ); float2 uvrange = saturate( fFocusAverageRange ); float2 uvstart = saturate( uvcenter - ( uvrange * 0.5 ) ); float2 uvfinish = saturate( uvcenter + ( uvrange * 0.5 ) ); float2 uvrate = min( ( uvrange * 0.5 ), fFocusAverageSampleRate ); float depthsamples = 1.0; for( float u = uvstart.x; u <= uvfinish.x; u += uvrate.x ) { for( float v = uvstart.y; v <= uvfinish.y; v += uvrate.y ) { float4 uv = float4( u, v, 0.0, fFocusSystemLOD ); float depth = tex2Dlod( SamplerDepth, uv ).x; res += depth; depthsamples += 1.0; } } res /= depthsamples; #endif // Nearest Focusing #ifdef USE_FOCUS_NEAREST float2 uvcenter = saturate( fFocusNearestCenter ); float2 uvrange = saturate( fFocusNearestRange ); float2 uvstart = saturate( uvcenter - ( uvrange * 0.5 ) ); float2 uvfinish = saturate( uvcenter + ( uvrange * 0.5 ) ); float2 uvrate = min( ( uvrange * 0.5 ), fFocusNearestSampleRate ); for( float u = uvstart.x; u <= uvfinish.x; u += uvrate.x ) { for( float v = uvstart.y; v <= uvfinish.y; v += uvrate.y ) { float4 uv = float4( u, v, 0.0, fFocusSystemLOD ); float depth = tex2Dlod( SamplerDepth, uv ).x; res = min( res, depth ); } } #endif // First Person Smart Focusing #ifdef USE_FOCUS_FIRST float2 uvstart = fFocusSmart1stWindow.xy; float2 uvfinish = fFocusSmart1stWindow.zw; float2 uvrate = min( float2( 0.005, 0.005 ), fFocusSmart1stSampleRate ); float depthwin = DistanceToDepth( fFocusSmart1stCutoffWindow ); float depthret = DistanceToDepth( fFocusSmart1stCutoffReticule ); float4 uvret = fFocusSmart1stReticule; for( float u = uvstart.x; u <= uvfinish.x; u += uvrate.x ) { for( float v = uvstart.y; v <= uvfinish.y; v += uvrate.y ) { float4 uv = float4( u, v, 0.0, fFocusSystemLOD ); float depth = tex2Dlod( SamplerDepth, uv ).x; bool inreticule = false; if( u > uvret.x && u < uvret.z && v > uvret.y && v < uvret.w && depth > depthret ) { inreticule = true; } if( depth > depthwin || inreticule == true ) { res = min( res, depth ); } } } #endif // Third Person Smart Focusing #ifdef USE_FOCUS_THIRD float2 uvstart = fFocusSmart3rdWindow.xy; float2 uvfinish = fFocusSmart3rdWindow.zw; float2 uvrate = min( float2( 0.005, 0.005 ), fFocusSmart3rdSampleRate ); float depthmin = DistanceToDepth( fFocusSmart3rdCutoffMin ); float depthmax = DistanceToDepth( fFocusSmart3rdCutoffMax ); if( res < depthmin ) { res = 1.0; } if( res > depthmax ) { for( float u = uvstart.x; u <= uvfinish.x; u += uvrate.x ) { for( float v = uvstart.y; v <= uvfinish.y; v += uvrate.y ) { float4 uv = float4( u, v, 0.0, fFocusSystemLOD ); float depth = tex2Dlod( SamplerDepth, uv ).x; if( depth > depthmin ) { res = min( res, depth ); } } } } #endif float FinalDistance = DepthToDistance( res ); FinalDistance *= fFocusSystemMult; FinalDistance += fFocusSystemBias; FinalDistance = max( FinalDistance, fFocusSystemMin ); FinalDistance = min( FinalDistance, fFocusSystemMax ); res = DistanceToDepth( FinalDistance ); #endif return res; } float4 PS_WriteFocus(VS_OUTPUT_POST IN) : COLOR { float res = 0.0; float curr = tex2D( SamplerCurr, 0.5 ).x; float prev = tex2D( SamplerPrev, 0.5 ).x; res = lerp( prev, curr, saturate(FadeFactor) ); #ifdef ENABLE_FOCUS_SYSTEM #ifdef USE_FOCUS_THIRD res = lerp(prev, curr, (Timer.w / fFocusSmart3rdSpeed) ); #endif #endif res = saturate(res); return res; } VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN) { VS_OUTPUT_POST OUT; float4 pos = float4( IN.pos.x, IN.pos.y, IN.pos.z, 1.0 ); OUT.vpos = pos; OUT.txcoord.xy = IN.txcoord.xy; return OUT; } /* Chromatic Aberration by Matso */ float4 PS_ProcessPass_Chroma(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR { float2 coord = float2( IN.txcoord.x, IN.txcoord.y ); float4 result = 0.0; #ifdef ENABLE_CHROMA result = ChromaticAberration(coord.xy, 0.0); #endif #ifndef ENABLE_CHROMA result = tex2D( SamplerColor, coord.xy ); #endif result.a = 1.0; return result; } /* Fast Depth of Field by Matso */ float4 PS_ProcessPass_FastDoF(VS_OUTPUT_POST IN, float2 vPos : VPOS, uniform int axis) : COLOR { float4 res; float2 coord = IN.txcoord.xy; float4 tcol = tex2D(SamplerColor, coord.xy); float sd = tex2D(SamplerDepth, coord).x; // generate the focus point of the float sf = tex2D(SamplerFocus, 0.5).x; sf = min( DistanceToDepth( fFastApertureMaxFocus ), sf ); float outOfFocus = DOF(sd, sf); float offset[4] = { -1.282, -0.524, 0.524, 1.282 }; // float2 tdirs[4] = { float2(1.0, 0.0), float2(0.0, 1.0), float2(0.707, 0.707), float2(-0.707, 0.707) }; //CHANGED DIRECTION OF BLURRING HERE float2 tdirs[4] = { float2(1.0, 0.0), float2(1.0, 0.0), float2(0.707, 0.0), float2(-0.707, 0.0) }; float blur = DOF_SCALE * outOfFocus; // Added a cap to prevent excessive blur. blur = min( blur, fFastApertureMaxBlur ) * tempF3.y; //CHANGED RANGE OF BLURRING blur*=EDirectionalBlurMultiplier; float wValue = 1.0; tdirs[axis].x *= ScreenSize.y; tdirs[axis].y *= ScreenSize.y * ScreenSize.z; #ifdef USE_FAST_DOF_BOKEH blur *= 0.25; #endif // Loop through the offsets for (int i = 0; i < 4; i++) { // generate the texture coordinate sampling offset (from current sample point) float2 tdir = offset[i] * tdirs[axis] * blur; // add the sampling offset to the actual texture coordinate coord.xy = IN.txcoord.xy + tdir.xy; float4 ct = tex2D(SamplerColor, coord.xy); #ifdef USE_FAST_DOF_CHROMA // generate chromatic aberation based on how out of focus the sample point is ct = ChromaticAberrationFocus(coord.xy, outOfFocus); #endif // specify the weight of the blur float w = 1.0 + abs(offset[i]); // weight blur for better effect // get the depth of the sample at that new coordinate float ds = tex2D(SamplerDepth, coord.xy).x; #ifdef USE_FAST_DOF_BOKEH // Matso's pseudo-bokeh weighting float b = GrayScale(ct.rgb) + length(ct.rgb) + 0.1; w = pow(b, fFastBokehCurve) + abs(offset[i]); #endif /////////////////////////////////////////////////////////////////// // Depth of Field Modifications by Michael Tichenor [IndigoNeko) // /////////////////////////////////////////////////////////////////// float bgoff = DOF(ds,sf); if( ( sd + 0.0 > sf + 0.0 ) && bgoff < 0.02 ) //&& ( ds + 0.0 < sf + 0.1) ) { w *= bgoff * 50.0; } if( ( sd + 0.0 < sf + 0.0 ) || ( ds + 0.0 > sf + 0.0 ) ) { tcol += ct * w; wValue += w; } /////////////////////////////////////////////////////////////////////// // End Depth of Field Modifications by Michael Tichenor [IndigoNeko) // /////////////////////////////////////////////////////////////////////// } // Average the accumulated colors. tcol /= wValue; // Put the new bokeh sampled DoF colors into the result. res.xyz = tcol.xyz; res.w = 1.0; return res; } ////////////////////////////// // Simple DoF by IndigoNeko // ////////////////////////////// float4 PS_ProcessPass_SimpleDoF(VS_OUTPUT_POST IN, float2 vPos : VPOS, uniform int Axis) : COLOR { float FocusDepth = tex2D( SamplerFocus, 0.5 ).x; float FocusDistance = DepthToDistance( FocusDepth ); float2 SampleTexCoord = IN.txcoord.xy; float4 SampleColor = tex2D( SamplerColor, SampleTexCoord.xy ); float SampleWeight = 1.0; float SampleDepth = tex2D(SamplerDepth, SampleTexCoord.xy).x; float SampleDistance = DepthToDistance( SampleDepth ); float SampleDiameter = CircleofConfusion( FocusDistance, SampleDistance ); SampleDiameter = min( fSimpleDoFMaxBlur, SampleDiameter ); float2 SampleTexels = float2( ScreenSize.x, ScreenSize.x * ScreenSize.w ); float2 SampleTexCoordPerTexel = float2( ScreenSize.y, ScreenSize.y * ScreenSize.z ); float TexDirectionOffset[4] = { -1.0, -0.5, 0.5, 1.0 }; float2 TexCoordOffset[4] = { float2(0.707, 0.707), float2(-0.707, 0.707), float2(1.0, 0.0), float2(0.0, 1.0), }; // Loop through the offsets for bokeh TexCoordOffset[Axis].x *= SampleTexCoordPerTexel.x; TexCoordOffset[Axis].y *= SampleTexCoordPerTexel.y; for (int i = 0; i < 4; i++) { // generate the texture coordinate sampling offset (from current sample point) float2 tdir = ( TexDirectionOffset[i] * TexCoordOffset[Axis] ) * SampleDiameter * 0.5; // add the sampling offset to the actual texture coordinate float4 BokehTexCoord = float4( SampleTexCoord.x + tdir.x, SampleTexCoord.y + tdir.y, 0.0, 1.0 ); float4 BokehColor = tex2Dlod(SamplerColor, BokehTexCoord ); // specify the weight of the blur float BokehWeight = 1.0; // get the depth of the sample at that new coordinate float BokehDepth = tex2Dlod(SamplerDepth, BokehTexCoord).x; float BokehDistance = DepthToDistance( BokehDepth ); float BokehDiameter = CircleofConfusion( FocusDistance, BokehDistance ); float BokehLuminance = Luminance( BokehColor.rgb ); BokehWeight += pow( BokehLuminance, fBokehCurve ) * fBokehMult; // TODO: Limit weight based on distance, so that we don't have color bleeding from objects in background onto foreground or vice versa. SampleColor += BokehColor * BokehWeight; SampleWeight += BokehWeight; } // Average the accumulated colors. SampleColor /= SampleWeight; SampleColor.w = 1.0; // Put the new bokeh sampled DoF colors into the result. return SampleColor; } ///////////////////////////////////////////// // Sprite DoF (EXPERIMENTAL) by IndigoNeko // ///////////////////////////////////////////// float4 PS_ProcessPass_SpriteDoF(VS_OUTPUT_POST IN, float2 vPos: VPOS) : COLOR { // Get Camera Focus Distance float2 FocusTexCoord = float2( 0.5, 0.5 ); float FocusDepth = tex2D( SamplerFocus, FocusTexCoord ).x; float FocusDistance = DepthToDistance( FocusDepth ); float CoCScale = 2.0; // Get Current Pixel Distance float2 SampleTexCoord = float2( IN.txcoord.x, IN.txcoord.y ); float4 SampleColor = tex2D( SamplerColor, SampleTexCoord ); SampleColor.w = 1.0; float SampleDepth = tex2D( SamplerDepth, SampleTexCoord ).x; float SampleDistance = DepthToDistance( SampleDepth ); // Calculate the size of the Circle of Confusion for the current pixel. float2 SampleTexels = float2( ScreenSize.x, ScreenSize.x * ScreenSize.w ); float2 SampleTexCoordPerTexel = float2( ScreenSize.y, ScreenSize.y * ScreenSize.z ); float SampleDiameter = CircleofConfusion( FocusDistance, SampleDistance ) * CoCScale; // Determine how many pixels we will sample around the current pixel for bokeh interference. float2 BokehSamples = fBokehSpriteMax; #ifdef USE_SPRITE_HACK BokehSamples = float2( SampleDiameter, SampleDiameter ); #endif float2 BokehTexels = clamp( BokehSamples, fBokehSpriteMin, fBokehSpriteMax ); float2 BokehTexCoordStart = SampleTexCoord - ( 0.5 * BokehTexels * SampleTexCoordPerTexel ); float2 BokehTexCoordFinish = SampleTexCoord + ( 0.5 * BokehTexels * SampleTexCoordPerTexel ); float4 BokehTexCoord = float4( 0.0, 0.0, 0.0, 1.0 ); float4 BokehColor = SampleColor; // Check all nearby texels to see if their bokeh will affect the current sample. for( float x = 0.0; x < BokehTexels.x; x += 1.0 ) { for( float y = 0.0; y < BokehTexels.y; y += 1.0 ) { BokehTexCoord.x = BokehTexCoordStart.x + ( x * SampleTexCoordPerTexel.x ); BokehTexCoord.y = BokehTexCoordStart.y + ( y * SampleTexCoordPerTexel.y ); float BokehDepth = tex2Dlod( SamplerDepth, BokehTexCoord ).x; float BokehDistance = DepthToDistance( BokehDepth ); float BokehDiameter = CircleofConfusion( FocusDistance, BokehDistance ) * CoCScale; BokehDiameter = max( BokehDiameter, 1.0 ); float2 BokehToSampleTexCoord = BokehTexCoord - SampleTexCoord; float2 BokehToSampleTexels = BokehToSampleTexCoord * SampleTexels; if( abs( BokehToSampleTexels.x ) <= BokehDiameter && abs( BokehToSampleTexels.y ) <= BokehDiameter && ( BokehDistance < SampleDistance + 1.0 || BokehDistance + 10.0 > FocusDistance || BokehDistance < FocusDistance ) ) { // Bokeh will affect current sample. float4 TempColor = tex2Dlod( SamplerColor, BokehTexCoord ); float TempIntensity = dot( float3( 0.3, 0.6, 0.1 ), TempColor.xyz ); float4 SpriteTexCoord = float4( 1.0 - ( x / BokehTexels.x ), 1.0 - ( y / BokehTexels.y ), 0.0, 1.0 ); float SpriteIntensity = tex2Dlod( SamplerPalette, SpriteTexCoord ).w; float BokehIntensity = pow( TempIntensity, fBokehCurve ) * fBokehMult * SpriteIntensity; BokehColor.xyz += TempColor.xyz * BokehIntensity; BokehColor.w += BokehIntensity; } } } float4 Color = BokehColor; Color /= Color.w; return Color; } //////////////// // TECHNIQUES // //////////////// technique ReadFocus { pass P0 { VertexShader = compile vs_3_0 VS_Focus(); PixelShader = compile ps_3_0 PS_ReadFocus(); ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique WriteFocus { pass P0 { VertexShader = compile vs_3_0 VS_Focus(); PixelShader = compile ps_3_0 PS_WriteFocus(); ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_Chroma(); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } #ifdef ENABLE_SPRITE_DOF pass P1 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_SpriteDoF(); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } #endif } #ifdef ENABLE_SIMPLE_DOF technique PostProcess2 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_SimpleDoF(0); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess3 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_SimpleDoF(1); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess4 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_SimpleDoF(2); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess5 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_SimpleDoF(3); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } #endif #ifdef ENABLE_FAST_DOF technique PostProcess2 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_FastDoF(FIRST_PASS); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess3 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_FastDoF(SECOND_PASS); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess4 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_FastDoF(THIRD_PASS); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } technique PostProcess5 { pass P0 { VertexShader = compile vs_3_0 VS_PostProcess(); PixelShader = compile ps_3_0 PS_ProcessPass_FastDoF(FOURTH_PASS); DitherEnable = FALSE; ZEnable = FALSE; CullMode = NONE; ALPHATESTENABLE = FALSE; SEPARATEALPHABLENDENABLE = FALSE; AlphaBlendEnable = FALSE; StencilEnable = FALSE; FogEnable = FALSE; SRGBWRITEENABLE = FALSE; } } #endif