Need a unique gift idea?
A Pastebin account makes a great Christmas gift
SHARE
TWEET

Tyler Howard - SSAO Example Code

a guest Mar 4th, 2013 19 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  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
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top