Guest User

Tyler Howard - SSAO Example Code

a guest
Mar 4th, 2013
43
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //Tyler Howard
  2. //
  3. //Screen Space Ambient Occlusion
  4. //
  5. //For the sake of explanation and brevity, this file contains relevant
  6. //excerpts from multiple files.
  7. //
  8. //
  9. //Basic overview:
  10. //
  11. //To obtain a screen-space ambient occlusion effect,
  12. //we need to make multiple rendering passes for the post-process
  13. //shader to eventually do its work.
  14. //
  15. //Pass 1 is a render of the scene's depth - linear distance instead
  16. //of the GPU's distance^2, since we want precision. Basically,
  17. //in addition to storing color information on a final output texture,
  18. //we store the distance from the camera to the rendered pixel.
  19. //
  20. //Pass 2 is the creation of the Ambient Occlusion texture. We
  21. //load a texture created by a random noise function and take samples
  22. //from around the pixel to reduce banding. The output is a single
  23. //float, which describes how occluded the pixel is by its surroundings:
  24. //0.0 for "completely blocked by surrounding pixels,"
  25. //1.0 for "not occluded at all." The result is a grainy black and
  26. //white texture.
  27. //
  28. //Pass 3 is the final post-process where we multiply the diffuse
  29. //color from pass 1 with the occlusion value we get by averaging
  30. //the surrounding pixels of pass 2. (We could sample from pass 2's
  31. //texture directly, but that results in a very grainy look.)
  32.  
  33. //////////////////////////////////////////////////////////////////////
  34. //
  35. //Model.cpp (or other objects' draw functions)
  36. //
  37. //Pass 1: Diffuse and Depth
  38.  
  39. void Model::Draw()
  40. {
  41.     //Hypothetical example - in reality, we'd batch draw calls
  42.     //by shader to change GPU state as little as possible.
  43.  
  44.     BindBuffers( m_VBO, m_IBO );
  45.     DrawIndicesWithTechnique( m_numVerts, m_numIndices,
  46.         Shader* m_diffuse, 0, 0 );
  47.     DrawIndicesWithTechnique( m_numVerts, m_numIndices,
  48.         Shader* m_depth, 0, 0 );
  49. }
  50.  
  51. //////////////////////////////////////////////////////////////////////
  52. //
  53. //Renderer.cpp
  54. //
  55. //Passes 2 and 3: Ambient Occlusion and Post-Processing
  56.  
  57.  
  58. void Renderer::Present(vec4 clearColor)
  59. {
  60.     BindBuffers(m_fullscreenVBO, m_fullscreenIBO);
  61.  
  62.     //Pass 2: Ambient Occlusion
  63.     SetRenderTarget(m_AmbientOcclusionTexture);
  64.  
  65.    
  66.     //SI_TEXTURE_1 is diffuse from pass 1
  67.     //SI_TEXTURE_2 is depth from pass 1
  68.     ApplyTexture(SI_TEXTURE_3, m_randomNoiseTexture);
  69.    
  70.     DrawIndicesWithTechnique( 4, 6, m_AmbientOcclusionTechnique,
  71.         0, 0 );
  72.  
  73.     //Pass 3: Final post-process and output
  74.     SetRenderTarget(m_PostProcessTexture);
  75.  
  76.     ApplyTexture(SI_TEXTURE_6, m_AmbientOcclusionTexture);
  77.  
  78.     DrawIndicesWithTechnique( 4, 6, m_PostProcessTechnique,
  79.         0, 0 );
  80.  
  81.  
  82.     HRESULT errcheck = m_swapchain->Present(0, 0);
  83.     CheckError(errcheck);
  84.  
  85.     ClearDepthBuffer();
  86. }
  87.  
  88. //////////////////////////////////////////////////////////////////////
  89. //
  90. //shader.fx - HLSL version of code
  91. //
  92.  
  93. ///////////////////////
  94. //Pass 1: Depth (and Diffuse, which isn't shown)
  95.  
  96. struct VtoDepth
  97. {
  98.     float4 pos:SV_POSITION;
  99.     float4 worldpos:WORLDPOS;
  100. };
  101.  
  102. void Depth_VS(
  103.     float4 pos:POSITION,
  104.     float4 tc:TEXCOORDS,
  105.     out VtoDepth vtd)
  106. {
  107.     vtd.pos = mul(pos, in_mvp);
  108.     vtd.worldpos = pos;
  109. }
  110.  
  111. float4 Depth_PS(VtoDepth vtd):SV_Target
  112. {
  113.     return float4(length(in_camerapos.xyz - vtd.worldpos.xyz));
  114. }
  115.  
  116. technique11 Depth
  117. {
  118.     pass P0
  119.     {
  120.         SetVertexShader(CompileShader(vs_4_0, Depth_VS()));
  121.         SetGeometryShader(NULL);
  122.         SetPixelShader(CompileShader(ps_4_0, Depth_PS()));
  123.     }
  124. }
  125.  
  126. ///////////////////////
  127. //Pass 2: Ambient Occlusion
  128.  
  129. struct VtoAmbientOcclusion
  130. {
  131.     float4 pos:SV_POSITION;
  132.     float4 tc:TEXCOORD;
  133. };
  134.  
  135. void AmbientOcclusion_VS(
  136.     float4 pos:POSITION,
  137.     float4 normal:NORMAL,
  138.     float4 tangent:TANGENT,
  139.     float4 tc:TEXCOORD,
  140.     out VtoAmbientOcclusion vtao)
  141. {
  142.     vtao.pos = pos;
  143.     vtao.tc = tc;
  144. }
  145.  
  146. //rotating kernel - we combine this with random noise
  147. //to get a randomly distributed set of points around each pixel
  148. //to reduce banding
  149.  
  150. static const float2 AO_SAMPLES[8] =
  151. {
  152.    float2(-0.71, 0.71), float2(0, 1),
  153.    float2(0.71, 0.71),  float2(0, -1),
  154.    float2(1, 0),        float2(0.71, -0.71),
  155.    float2(-1, 0),       float2(-0.71, -0.71)
  156. };
  157.  
  158. float4 AmbientOcclusion_PS(VtoAmbientOcclusion vtao):SV_Target
  159. {
  160.  
  161.     //currently bound to in_texture2: Random Noise
  162.     //currently bound to in_texture3: Scene Depth
  163.  
  164.     float3 rand = normalize
  165.         (in_texture2.Sample(ao, vtao.tc.xy).xyz) * 2.0 - 1.0;
  166.  
  167.     float thisPixelDepth = in_texture3.Sample(ao, vtao.tc.xy).w;
  168.  
  169.     float sum = 0.0;
  170.    
  171.     for(int i = 0; i < 8; ++i)      //8 rings
  172.     {
  173.         for(int k = 0; k < 8; ++k)  //8 points on that ring
  174.         {
  175.             float2 sampleUVs = vtao.tc.xy + (k / 8.0) *                     (AO_SAMPLES[k] + rand.xy) *
  176.                 float2( 1.0 / in_screenWidth,
  177.                 1.0 / in_screenHeight );
  178.  
  179.             float samplePixelDepth =
  180.                 in_texture3.Sample(ao, sampleUVs).x;
  181.  
  182.             float delta =
  183.                 thisPixelDepth - samplePixelDepth;
  184.  
  185.             if( delta > 1.0 && delta < 10.0)
  186.             {
  187.                 sum += 1.0;
  188.             }
  189.         }
  190.     }
  191.  
  192.     //get % of surrounding pixels that occlude this one
  193.     float occ = 1.0 - (sum / 64.0);
  194.    
  195.     return float4(occ, occ, occ, 1.0);
  196. }
  197.  
  198. technique11 AmbientOcclusion
  199. {
  200.     pass P0
  201.     {
  202.         SetVertexShader(CompileShader(vs_4_0,                       AmbientOcclusion_VS()));
  203.         SetGeometryShader(NULL);
  204.         SetPixelShader(CompileShader(ps_4_0,                        AmbientOcclusion_PS()));
  205.     }
  206. }
  207.  
  208. ///////////////////////
  209. //Pass 3: Final post-process and render
  210.  
  211. struct VtoPostprocess
  212. {
  213.     float4 pos:SV_POSITION;
  214.     float4 tc:TEXCOORD;
  215. };
  216.  
  217. void postprocessVS(
  218.     float4 pos:POSITION,
  219.     float4 tc:TEXCOORD,
  220.     out VtoPostprocess vtpp)
  221. {
  222.     vtpp.pos = pos;
  223.     vtpp.tc = tc;
  224. }
  225.  
  226. //lower = grainer, higher = smokier/smoother
  227. static const int SSAO_BLUR_AMOUNT = 8;
  228.  
  229. float4 postprocessPS(VtoPostprocess vtpp):SV_Target
  230. {
  231.     //currently bound to in_texture1: Diffuse map from pass 1
  232.     //currently bound to in_texture6: Ambient Occlusion pass 2
  233.  
  234.     float4 sceneColor = in_texture1.Sample(defss, vtpp.tc.xy);
  235.        
  236.     sceneColor = toneMap(sceneColor, in_texture6.Sample(defss,      float2(0.5, 0.5)));
  237.  
  238.     //get occlusion and blur from surrounding pixels
  239.     //so that end result isn't grainy
  240.  
  241.     float occ = 0.0;
  242.     for(int x = 0; x < SSAO_BLUR_AMOUNT; ++x)
  243.     {
  244.         for(int y = 0; y < SSAO_BLUR_AMOUNT; ++y)
  245.         {
  246.             occ += in_texture8.Sample(defss, vtpp.tc.xy,                int2(x - SSAO_BLUR_AMOUNT * 0.5,
  247.             y - SSAO_BLUR_AMOUNT * 0.5)).x;
  248.         }
  249.     }
  250.     occ /= (SSAO_BLUR_AMOUNT * SSAO_BLUR_AMOUNT);
  251.    
  252.     return sceneColor * occ;
  253. }
  254.  
  255. technique11 postprocess
  256. {
  257.     pass P0
  258.     {
  259.         SetVertexShader(CompileShader(vs_4_0,
  260.             postprocessVS()));
  261.         SetGeometryShader(NULL);
  262.         SetPixelShader(CompileShader(ps_4_0, postprocessPS()));
  263.     }
  264. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×