Ignore:
Timestamp:
08/26/08 16:27:11 (16 years ago)
Author:
mattausch
Message:

changed ssao to multipass algorithm

File:
1 edited

Legend:

Unmodified
Added
Removed
  • GTP/trunk/App/Demos/Vis/FriendlyCulling/src/shaders/ssao.cg

    r2809 r2868  
     1//////////////////// 
     2// Screen Spaced Ambient Occlusion shader 
     3// based on shader of Alexander Kusternig 
     4 
     5//#define NUM_SAMPLES 8 
     6#define NUM_SAMPLES 16 
     7 
     8// rule of thumb: approx 1 / NUM_SAMPLES 
     9#define SAMPLE_INTENSITY 0.15 
     10//#define SAMPLE_INTENSITY 0.125f 
     11 
     12#define AREA_SIZE 9e-1f 
     13//#define VIEW_CORRECTION_SCALE 0.3f 
     14#define VIEW_CORRECTION_SCALE 0.5f 
     15#define DISTANCE_SCALE 1e-6f 
     16 
     17 
    118struct fragment 
    219{ 
    3     float4 pos: WPOS; // normalized screen position 
    4     float4 view: COLOR; 
    5     float4 texcoord: TEXCOORD0;       
    6     float4 lindepth: TEXCOORD1; 
     20        // normalized screen position 
     21        float4 pos: WPOS; 
     22        float4 texCoord: TEXCOORD0;  
     23        float3 view: COLOR0; 
    724}; 
    825 
     
    1027struct pixel 
    1128{ 
    12     float4 col: COLOR0; 
     29        float4 color: COLOR0; 
    1330}; 
    1431 
    1532 
    16 float3 reflect(float3 pt, float3 n) 
     33float2 reflect(float2 pt, float2 n) 
    1734{ 
    1835  // distance to plane 
    1936  float d = dot(n, pt); 
    2037  // reflect around plane 
    21   float3 rpt = pt - d * 2.0f * n; 
    22    
    23   //return pt; 
     38  float2 rpt = pt - d * 2.0f * n; 
     39 
    2440  return rpt; 
    2541} 
    2642 
    2743 
     44float2 rotate(float2 pt, float2 n) 
     45{ 
     46        float2 ptTransformed; 
     47        ptTransformed.x = n.r * pt.x - n.g * pt.y; 
     48        ptTransformed.y = n.g * pt.x + n.r * pt.y; 
     49 
     50        return ptTransformed; 
     51} 
     52 
     53 
     54/** The ssao shader returning the an intensity value between 0 and 1 
     55*/ 
     56float ssao(fragment IN, 
     57                   uniform sampler2D positions, 
     58                   uniform sampler2D noiseTexture, 
     59                   uniform float2 samples[NUM_SAMPLES], 
     60                   uniform float3 currentNormal, 
     61                   uniform float3 currentViewDir, 
     62                   uniform float noiseMultiplier, 
     63                   uniform float4 centerPosition 
     64                   ) 
     65{ 
     66        // the w coordinate from the persp. projection 
     67        float w = centerPosition.w; 
     68 
     69        // Check in a circular area around the current position. 
     70        // Shoot vectors to the positions there, and check the angle to these positions. 
     71        // Summing up these angles gives an estimation of the occlusion at the current position. 
     72 
     73        float total_ao = 0.0; 
     74 
     75        const float areaSize = 5e-1f; 
     76 
     77        for (int i = 0; i < NUM_SAMPLES; i ++)  
     78        { 
     79                float2 offset = samples[i]; 
     80 
     81                //sample noisetex; r stores costheta, g stores sintheta 
     82                //float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy * noiseMultiplier).xy * 2.0f - 1.0f; 
     83                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy * noiseMultiplier).xy; 
     84 
     85                // rotation 
     86                //float2 offsetTransformed = offset; 
     87                //float2 offsetTransformed = rotate(offset, mynoise); 
     88                float2 offsetTransformed = reflect(offset, mynoise); 
     89 
     90                // weight with projected coordinate to reach similar kernel size for near and far 
     91                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * w; 
     92 
     93                // sample downsampled texture in order to speed up texture accesses 
     94                float3 sample_position = tex2Dlod(positions, float4(texcoord, 0, 1)).xyz; 
     95                //float3 sample_position = tex2D(positions, texcoord).xyz; 
     96 
     97                float3 vector_to_sample = sample_position - centerPosition.xyz; 
     98                float length_to_sample = length(vector_to_sample); 
     99                float3 direction_to_sample = vector_to_sample / length_to_sample; 
     100 
     101                // Angle between current normal and direction to sample controls AO intensity. 
     102                float cos_angle = dot(direction_to_sample, currentNormal); 
     103                cos_angle = max(cos_angle, 0.0f); 
     104 
     105                // distance between current position and sample position controls AO intensity. 
     106                float distance_intensity =  
     107                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample); 
     108 
     109                // if surface normal perpenticular to view dir, some samples probably count less  
     110                // => compensate for this 
     111                float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal)); 
     112 
     113                total_ao += cos_angle * distance_intensity * view_correction; 
     114        } 
     115 
     116        return (1.0f - total_ao); 
     117        //return dot(currentViewDir, currentNormal); 
     118} 
     119 
     120 
     121/** Computes ambient occlusion + diffuse reflections 
     122*/ 
     123float4 globIllum(fragment IN, 
     124                                 uniform sampler2D colors, 
     125                                 uniform sampler2D positions, 
     126                                 uniform sampler2D noiseTexture, 
     127                                 uniform float2 samples[NUM_SAMPLES], 
     128                                 uniform float3 currentNormal, 
     129                                 uniform float3 currentViewDir, 
     130                                 uniform float noiseMultiplier, 
     131                                 uniform float4 centerPosition 
     132                                 ) 
     133{ 
     134        // the w coordinate from the persp. projection 
     135        float w = centerPosition.w; 
     136 
     137        // Check in a circular area around the current position. 
     138        // Shoot vectors to the positions there, and check the angle to these positions. 
     139        // Summing up these angles gives an estimation of the occlusion at the current position. 
     140 
     141        float total_ao = 0.0; 
     142        float3 total_color = float3(0.0f); 
     143 
     144        const float areaSize = 5e-1f; 
     145 
     146        for (int i = 0; i < NUM_SAMPLES; i ++)  
     147        { 
     148                float2 offset = samples[i]; 
     149 
     150                //sample noisetex; r stores costheta, g stores sintheta 
     151                float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy * noiseMultiplier).xy * 2.0f - 1.0f; 
     152 
     153                // rotation 
     154                float2 offsetTransformed = rotate(offset, mynoise); 
     155 
     156                // weight with projected coordinate to reach similar kernel size for near and far 
     157                float2 texcoord = IN.texCoord.xy + offsetTransformed * AREA_SIZE * w; 
     158 
     159                float3 sample_position = tex2D(positions, texcoord).xyz; 
     160                float3 sample_color = tex2D(colors, texcoord).xyz; 
     161 
     162                float3 vector_to_sample = sample_position - centerPosition.xyz; 
     163                float length_to_sample = length(vector_to_sample); 
     164                float3 direction_to_sample = vector_to_sample / length_to_sample; 
     165 
     166                // Angle between current normal and direction to sample controls AO intensity. 
     167                float cos_angle = dot(direction_to_sample, currentNormal); 
     168                cos_angle = max(cos_angle, 0.0f); 
     169 
     170                // distance between current position and sample position controls AO intensity. 
     171                float distance_intensity =  
     172                        (SAMPLE_INTENSITY * DISTANCE_SCALE) / (DISTANCE_SCALE + length_to_sample * length_to_sample); 
     173 
     174                // if normal perpenticular to view dir, only half of the samples count 
     175                float view_correction = 1.0f + VIEW_CORRECTION_SCALE * (1.0f - dot(currentViewDir, currentNormal)); 
     176 
     177                total_ao += cos_angle * distance_intensity * view_correction; 
     178                total_color += cos_angle * distance_intensity * view_correction * sample_color * 0.3f; 
     179        } 
     180 
     181        return float4(total_color, 1.0f - total_ao); 
     182} 
     183 
     184 
     185/** The mrt shader for screen space ambient occlusion 
     186*/ 
    28187pixel main(fragment IN,  
    29            uniform sampler2D lindepth, 
    30            uniform sampler2D scene, 
    31            uniform sampler2D normal, 
    32            uniform float invTexSize, 
    33            uniform float radius, 
    34            uniform float3 eyevec, 
    35            uniform float3 samples[32]) 
    36 { 
    37     pixel OUT; 
     188                   uniform sampler2D colors, 
     189                   uniform sampler2D positions, 
     190                   uniform sampler2D normals, 
     191                   uniform sampler2D noiseTexture, 
     192                   uniform float2 samples[NUM_SAMPLES], 
     193                   uniform float noiseMultiplier, 
     194                   uniform sampler2D oldTex, 
     195                   const uniform float4x4 oldModelViewProj, 
     196                   uniform float maxDepth, 
     197                   uniform float expFactor 
     198                   ) 
     199{ 
     200        pixel OUT; 
     201 
     202        float4 normal = tex2D(normals, IN.texCoord.xy); 
     203         
     204        // the ambient term 
     205        float amb = normal.w; 
     206 
     207        // expand normal 
     208        normal = normalize(normal);// * 2.0f - 1.0f); 
     209        /// the current view direction 
     210        float3 viewDir = normalize(IN.view * 2.0f - float3(1.0f)); 
     211 
     212        // the current world position 
     213        float4 centerPosition = tex2D(positions, IN.texCoord.xy); 
     214         
     215        float4 col = tex2D(colors, IN.texCoord.xy); 
     216        float currentDepth = col.w; 
     217 
     218        float ao = ssao(IN, positions, noiseTexture, samples, normal.xyz, viewDir, noiseMultiplier, centerPosition); 
     219        float4 attenuated_color = ao * col; 
     220        //float4 attenuated_color = ao; 
     221 
     222        //float4 new_col = globIllum(IN, colors, positions, noiseTexture, samples, normal.xyz, viewDir, noiseMultiplier, centerPosition);  
     223        //float4 attenuated_color = ao * col + new_col; 
     224         
     225        const float x = expFactor; 
     226 
     227        float4 dummy = centerPosition * maxDepth; 
     228        dummy.w = 1.0f; 
     229 
     230        float4 oldPos = mul(oldModelViewProj, dummy); 
     231 
     232        float newDepth = oldPos.z / oldPos.w; 
    38233  
    39     // eye space z 
    40     float eyez = tex2D(lindepth, IN.texcoord.xy).x; 
    41  
    42     float3 viewvec = IN.view.xyz * 2.0f - float3(1.0f); 
    43     viewvec /= viewvec.z; 
    44  
    45     //return float4(viewvec.xyz, 1.0f); 
    46     // eye point 
    47     //float3 eyept = eyez * viewvec; 
    48     float3 eyept = float3(IN.texcoord.xy, eyez); 
    49  
    50     float4 pl = tex2D(normal, IN.pos.xy * invTexSize); 
    51     pl = pl * 2.0 - float4(1.0); 
    52  
    53     float occlusion = 0.0; 
    54  
    55     // gather occlusion from surrounding samples 
    56     for (int i = 0; i < 32; i ++) 
    57     { 
    58         // generate new sample point 
    59         //float3 samplepos = eyept + radius * samples[i]; 
    60         // create some dithering by reflecting the sample point alond some random plane 
    61         float3 samplepos = eyept + radius * reflect(samples[i], pl.xyz); 
    62  
    63         // project to texture space q: why the scaling? 
    64         float2 sampletex = (samplepos.xy / samplepos.z);// * float2(0.75, 1.0); 
    65          
    66         //float2 sampletexn = sampletex; 
    67         // normalize to [0 .. 1], move eye point to center 
    68         //float2 sampletexn = sampletex * 0.5f + float2(0.5f); 
    69         float2 sampletexn = sampletex + float2(0.5f); 
    70  
    71         // look up depth at sample point 
    72         float depth = tex2D(lindepth, sampletexn).x; 
    73         // compare: is point occluded? 
    74         //float zdist = 50.0f * max(-samplepos.z + depth, 0.0f); 
    75         float zdist = 50.0f * max(samplepos.z - depth, 0.0f); 
    76         // occlusion factor shrinks quadratic with distance to occluder 
    77         occlusion += 1.0 / (1.0 + zdist * zdist); 
    78         //occlusion += 1.0 / (1.0 + zdist); 
    79    } 
    80  
    81    // normalize 
    82    occlusion /= 32.0f; 
    83    
    84    OUT.col = 1.0f - occlusion; 
    85    //   OUT.col = tex2D(scene, IN.texcoord.xy) * 0.5 + (1.0f - occlusion); 
    86  
    87    return OUT; 
    88 } 
     234        float2 tex = (oldPos.xy / oldPos.w) * 0.5f + 0.5f; 
     235        float4 col1 = tex2D(oldTex, tex); 
     236 
     237        float oldDepth = col1.w; 
     238        float depthDif = 1.0f - newDepth / oldDepth; 
     239 
     240        if ((tex.x >= 0.0f) && (tex.x < 1.0f) &&  
     241                (tex.y >= 0.0f) && (tex.y < 1.0f) &&  
     242                (abs(depthDif)  < 1e-4f)) 
     243        { 
     244                OUT.color = attenuated_color * expFactor + col1 * float4(1.0f - expFactor); 
     245        } 
     246        else 
     247        { 
     248                OUT.color = attenuated_color; 
     249        } 
     250 
     251        //OUT.color.xyz = viewDir; 
     252        //OUT.color = attenuated_color; 
     253         
     254        OUT.color.w = currentDepth; 
     255 
     256        return OUT; 
     257} 
Note: See TracChangeset for help on using the changeset viewer.