Advertisement
Ineluki80

DarkVision.fx - NS2 Alien Vision Shader v0.3

Jan 26th, 2013
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.29 KB | None | 0 0
  1.     /*************************************************************************************\
  2.     *  Alien Vision Shader for Natural Selection 2                                        *
  3.     *  To be used with Dark Vision Mod for Natural Selection 2                            *
  4.     *  Steam Workshop: http://steamcommunity.com/sharedfiles/filedetails/?id=108510422    *
  5.     *  Forum: http://forums.unknownworlds.com/discussion/comment/2068226/#Comment_2068226 *
  6.     *  Example Video: http://www.youtube.com/watch?v=xXRCpaSsp_I                          *
  7.     *                                                                                     *
  8.     *  Author: Ineluki80                                                                  *
  9.     *  Date: 2013-01-29                                                                   *
  10.     *  Version: v0.3                                                                      *
  11.     *                                                                                     *
  12.     *  Features:                                                                          *
  13.     *    - short sighted aliens using depth of field technique ( Tiefenunschärfe )        *
  14.     *    - Insectoide compound eyes using a hexagonal lattice                             *
  15.     *    - Refraction and dispersion for eye vision                                       *
  16.     *    - brightness correction in dark spaces                                           *
  17.     *    - sonar sight using sound pulses with exponential decay and distance based       *
  18.     *      resolution, rainbow coloured                                                   *
  19.     *    - importance highlighting for biological and technological compounds             *
  20.     *                                                                                     *
  21.     \*************************************************************************************/
  22.      
  23.     struct VS_INPUT
  24.     {
  25.         float3 ssPosition   : POSITION;
  26.         float2 texCoord     : TEXCOORD0;
  27.         float4 color        : COLOR0;
  28.     };
  29.      
  30.     struct VS_OUTPUT
  31.     {
  32.         float4 ssPosition   : POSITION;
  33.         float2 texCoord     : TEXCOORD0;
  34.         float4 color        : COLOR0;
  35.     };
  36.      
  37.     struct PS_INPUT
  38.     {
  39.         float2 texCoord     : TEXCOORD0;
  40.         float4 color        : COLOR0;
  41.     };
  42.      
  43.     texture         baseTexture;
  44.     texture         depthTexture;
  45.     float           time;
  46.     float           startTime;
  47.     float           amount;
  48.      
  49.     sampler baseTextureSampler = sampler_state
  50.         {
  51.             texture       = (baseTexture);
  52.             AddressU      = Wrap;
  53.             AddressV      = Wrap;
  54.             MinFilter     = Linear;
  55.             MagFilter     = Linear;
  56.             MipFilter     = Linear;
  57.             SRGBTexture   = False;
  58.         };
  59.            
  60.     sampler depthTextureSampler = sampler_state
  61.         {
  62.             texture       = (depthTexture);
  63.             AddressU      = Clamp;
  64.             AddressV      = Clamp;
  65.             MinFilter     = Linear;
  66.             MagFilter     = Linear;
  67.             MipFilter     = None;
  68.             SRGBTexture   = False;
  69.         };
  70.      
  71.  
  72.     VS_OUTPUT SFXBasicVS(VS_INPUT input)
  73.     {
  74.      
  75.         VS_OUTPUT output;
  76.      
  77.         output.ssPosition = float4(input.ssPosition, 1);
  78.         output.texCoord   = input.texCoord;
  79.         output.color      = input.color;
  80.      
  81.         return output;
  82.      
  83.     }
  84.    
  85.   // Function to calculate optic dispersion
  86.   // - Refraction in the eye is a function of the place where the light hits it
  87.   // - Dispersion: Light of several wavelengths is affected in separate ways
  88.  
  89.     float4 OpticDispersion( float2 texCoord ) {                                               // Take the texture coordinates (interval[0..1]) and return a colour value
  90.       float  r   = tex2D(depthTextureSampler, texCoord).r;                                    // Get the distance to the pixel
  91.       float  px  = (texCoord.x-0.5)*2;                                                        // calculate the X coordinate in interval [-1.0 .. 1.0]
  92.       float  py  = (texCoord.y-0.5)*2;                                                        // calculate the Y coordinate in interval [-1.0 .. 1.0]
  93.       float  xyr = px*px + py*py;                                                             // Get the square of the radius in the XY plane
  94.       float  pz  = sqrt( r*r - xyr );                                                         // Reconstruct the original Z value from Distance and XY coordinates
  95.              xyr = sqrt( xyr );                                                               // Calculate the radius in the XY plane from its square
  96.       float  ef  = exp(-xyr/3);                                                               // Anisotropy Effect Factor increases with XY plane radius
  97.      
  98.       //if ( r < 0.4 ) { ef = pow(ef,1/3); }                                                    // If it is the mouth, we reduce the effect because otherwise it looks ugly
  99.    
  100.       float4 c;  c.a = 0;                                                                     // C holds the return colour. Its alpha value is zero
  101.            
  102.       // Red, green, and blue light obeys separate refraction constants. We use Refraction constants smaller than 1.0, so the effect is bigger on red and smaller on blue light.
  103.       // Also the effect is more pronounced in the outer parts of the eye, so the refraction constants are multiplied by the radial effect factor ef.
  104.       // We apply some refration based on the XYZ pixel coordinate relative to the Z normal vector (XY plane), and look where the new vector is located in the texture.
  105.       // To get valid texture coordinates, they have to be transformed into interval [0..1] again, and, to be sure, the value is cut outside this interval by clamp.      
  106.      
  107.       c.r = tex2D(baseTextureSampler, clamp(refract(float3(px, py, pz), float3(0,0,1), 0.980*ef), -1.0, 1.0).xy/2.0+0.5).r;  
  108.       c.g = tex2D(baseTextureSampler, clamp(refract(float3(px, py, pz), float3(0,0,1), 0.990*ef), -1.0, 1.0).xy/2.0+0.5).g;  
  109.       c.b = tex2D(baseTextureSampler, clamp(refract(float3(px, py, pz), float3(0,0,1), 0.999*ef), -1.0, 1.0).xy/2.0+0.5).b;  
  110.        
  111.       return c;                                                                               // Finally, we return the calculated colour.
  112.     }
  113.    
  114.   // Function to calculate optic distortion by refraction
  115.     float2 OpticDistortion( float2 texCoord, float refconst ) {                                // Take texture coordinates (interval[0..1]) and refraction constant, return new coordinates
  116.       float  r   = tex2D(depthTextureSampler, texCoord).r;                                    // Get the distance to the pixel
  117.       float  px  = (texCoord.x-0.5)*2;                                                        // calculate the X coordinate in interval [-1.0 .. 1.0]
  118.       float  py  = (texCoord.y-0.5)*2;                                                        // calculate the Y coordinate in interval [-1.0 .. 1.0]
  119.       float  xyr = px*px + py*py;                                                             // Get the square of the radius in the XY plane
  120.       float  pz  = sqrt( r*r - xyr );                                                         // Reconstruct the original Z value from Distance and XY coordinates
  121.              xyr = sqrt( xyr );                                                               // Calculate the radius in the XY plane from its square
  122.       float  ef  = exp(-xyr/3);                                                               // Anisotropy Effect Factor increases with XY plane radius
  123.      
  124.       //if ( r < 0.4 ) { ef = pow(ef,1/3); }                                                    // If it is the mouth, we reduce the effect because otherwise it looks ugly
  125.    
  126.       return clamp(refract(float3(px, py, pz), float3(0,0,1), refconst*ef), -1.0, 1.0).xy/2.0+0.5;   // Finally, we return the new coordinates
  127.     }
  128.  
  129.    
  130.     float4 SFXDarkVisionPS(PS_INPUT input) : COLOR0
  131.     {
  132.    
  133.     // Get the depth and importance information
  134.         float2 depthMap = tex2D(depthTextureSampler, input.texCoord).rg;                         // this texture contains the depth information in r and importance factor in g
  135.        
  136.     // Depth of field effect "Tiefenunschärfe"
  137.     //   - aliens are short sighted, pixels are increasingly blurred with respect to distance in a hexagonal shape
  138.    
  139.         const float d = 0.0050 * (1-exp(-depthMap.r/15.0));                                               // Blurring is affected by distance up to a maximal value
  140.         const float sqrt3over2 = sqrt(3)/2.0;                                                             // This factor is needed for the hexagon coordinates
  141.  
  142. /*        
  143. *  // Tiefenunschärfe (Depth of field) without Optic Dispersion - using original texture
  144. *         float4 outputPixel = ( tex2D(baseTextureSampler, input.texCoord + float2(+d,0)) +                 // Colour information of the six corners of a hexagon
  145. *                                tex2D(baseTextureSampler, input.texCoord + float2(+d/2,+d*sqrt3over2)) +   // (size varying with distance) is used to blurr the texture
  146. *                                tex2D(baseTextureSampler, input.texCoord + float2(-d/2,+d*sqrt3over2)) +   // by taking the mean of the colours. By this, bright spots
  147. *                                tex2D(baseTextureSampler, input.texCoord + float2(+d/2,-d*sqrt3over2)) +   // will be blurred into a hexagonal shape because their information
  148. *                                tex2D(baseTextureSampler, input.texCoord + float2(-d/2,-d*sqrt3over2)) +   // is used in several pixels throughout the texture.
  149. *                                tex2D(baseTextureSampler, input.texCoord + float2(-d,0))
  150. *                              ) / 6.0;
  151. */
  152.  
  153.       // Tiefenunschärfe (Depth of field) including Optic Dispersion - using refraction transformed texture
  154.         float4 outputPixel = ( OpticDispersion(input.texCoord + float2(+d,0)) +                           // Colour information of the six corners of a hexagon
  155.                                OpticDispersion(input.texCoord + float2(+d/2,+d*sqrt3over2)) +             // (size varying with distance) is used to blurr the texture
  156.                                OpticDispersion(input.texCoord + float2(-d/2,+d*sqrt3over2)) +             // by taking the mean of the colours. By this, bright spots
  157.                                OpticDispersion(input.texCoord + float2(+d/2,-d*sqrt3over2)) +             // will be blurred into a hexagonal shape because their information
  158.                                OpticDispersion(input.texCoord + float2(-d/2,-d*sqrt3over2)) +             // is used in several pixels throughout the texture.
  159.                                OpticDispersion(input.texCoord + float2(-d,0))                             // Instead of the original texture, its colour information is
  160.                              ) / 6.0;                                                                     // previously transformed by the OpticDispersion function.
  161.  
  162.  
  163.       // Darkness correction
  164.         float v = length(outputPixel);                                                                    // colour brightness is tuned using a polynomial
  165.         outputPixel = outputPixel*(0.05*v+0.94+0.01/v);                                                   // which limits darkness and is near linear otherwise
  166.  
  167.  
  168.       // Insectoid Eyes
  169.      
  170.         const  float  grain  = 50.0;                                                            // granularity of the eyes .. how many cells per row and column
  171.         const  float4 delta  = float4(-1.0,0.0,1.0,0.0)/3;                                      // offset for the different colour channels
  172.                float  x      = (input.texCoord.x) * grain;                                      // X and Y coordinates within the granularity
  173.                float  y      = (input.texCoord.y) * grain;        
  174.         float4 eyePattern    = 0.5+0.3*pow(fmod(delta+x,1.0) *                                  // creates a hexagonal grid, slightly dislocated for all colour channels
  175.                                            fmod(grain+delta+x/2+y*sqrt3over2,1.0) *             // The power function is used to limit the brightness contrast to the
  176.                                            fmod(grain+delta+x/2-y*sqrt3over2,1.0),1.3);         // edges instead of a linear interpolation
  177.  
  178.                                            
  179.       // Edge Highlighting
  180.        
  181.         float  offset   = 0.0010;                                                                // offset is the difference between two pixels for which we do an edge test.        
  182.         float4 ETest    = float4(
  183.                             tex2D(depthTextureSampler, input.texCoord + float2(-offset,0)).r,    // we get the depth value of each pixel around the one we want to shade
  184.                             tex2D(depthTextureSampler, input.texCoord + float2(+offset,0)).r,    // above in -x, now in +x direction
  185.                             tex2D(depthTextureSampler, input.texCoord + float2(0,-offset)).r,    // now in -y, next in +y direction
  186.                             tex2D(depthTextureSampler, input.texCoord + float2(0,+offset)).r
  187.                           );
  188.            
  189.         const float falloff = 10.0 / log(2);                                                     // edge intensity is halved for each 10 units, so it's 1/4 for 20 units, 1/8 for 30 units, ...
  190.         float edge = saturate (                                                                  // edge is the highlight amount of each pixel, has values between 0 and 1
  191.                        length(ETest-depthMap.r)*exp(-depthMap.r/falloff)                         // An edge is a pixel whose distance to its neighbours, scaled by the
  192.                      );                                                                          // exponential perception factor, is bigger than 1.0
  193.                      
  194.         // In addition to sharp edges, we can add a little bit of area coloring using optic distortion based blurring
  195.         ETest    = float4(
  196.                             tex2D(depthTextureSampler, OpticDistortion(input.texCoord + float2(-offset,0),0.990)).r,
  197.                             tex2D(depthTextureSampler, OpticDistortion(input.texCoord + float2(+offset,0),0.990)).r,
  198.                             tex2D(depthTextureSampler, OpticDistortion(input.texCoord + float2(0,-offset),0.990)).r,
  199.                             tex2D(depthTextureSampler, OpticDistortion(input.texCoord + float2(0,+offset),0.990)).r
  200.                           );                    
  201.         edge += 0.1* saturate(length(ETest-depthMap.r)*exp(-depthMap.r/falloff));
  202.  
  203.        
  204.       // Sonar effect                                                                            // By applying a time modified pulse using a slater function, we can
  205.         float sonar = 0.02+0.73*exp(-abs(depthMap.r-fmod(50*(time-startTime),100.0))/10.0);      // emulate a sonar. Sound travels 50 units per second, pulses are 10 units long
  206.                                                                                                  // and travel 100 units before the next pulse is emitted.
  207.                                                                                                  // Minimum brightness is 2%, maximum brightness is 75%.
  208.        
  209.       // Importance highlighting
  210.         float4 edgeColor;                                                                        // This will hold the colour of the edge based on information content.
  211.         if ( depthMap.g > 0.5 && depthMap.r > 0.4 ) {                                            // If the pixel belongs to something important (bio, tech, marines, etc)
  212.           edgeColor   = float4( 2.97, 0.37, -0.13, 0.0 ) * depthMap.g;                           // and the distance is bigger than 0.4 units (so we ignore our snoute).
  213.           outputPixel = outputPixel + 0.1*edgeColor;                                             // We set the edge colour to a bright orange weighted by importance, and
  214.           edge        = edge * 5.0;                                                              // overlay the object colour with that orange, too. Finally we add some
  215.         } else {                                                                                 // glow effect to the edges by oversaturating them via a huge factor.
  216.           edgeColor = (1+cos((sonar+float4(0,1,2,0)/3)*3.1415927*2))/2;                          // If the object is not important, edge colour is a rainbow coloured pulse.
  217.         }
  218.        
  219.       // Adding all information together
  220.         return outputPixel*eyePattern + edge*edgeColor*sonar;                                    // We overlay the rendered scene with our eyePattern and add coloured edges.
  221.                                                                                                  // Finally, we return the calculated colour as result.
  222.     }
  223.      
  224.     technique SFXDarkVision
  225.     {
  226.         pass p0
  227.         {
  228.             ZEnable             = False;
  229.             ZWriteEnable        = False;  
  230.             VertexShader        = compile vs_3_0 SFXBasicVS();
  231.             PixelShader         = compile ps_3_0 SFXDarkVisionPS();
  232.             CullMode            = None;
  233.         }
  234.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement