Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Tyler Howard
- //
- //Screen Space Ambient Occlusion
- //
- //For the sake of explanation and brevity, this file contains relevant
- //excerpts from multiple files.
- //
- //
- //Basic overview:
- //
- //To obtain a screen-space ambient occlusion effect,
- //we need to make multiple rendering passes for the post-process
- //shader to eventually do its work.
- //
- //Pass 1 is a render of the scene's depth - linear distance instead
- //of the GPU's distance^2, since we want precision. Basically,
- //in addition to storing color information on a final output texture,
- //we store the distance from the camera to the rendered pixel.
- //
- //Pass 2 is the creation of the Ambient Occlusion texture. We
- //load a texture created by a random noise function and take samples
- //from around the pixel to reduce banding. The output is a single
- //float, which describes how occluded the pixel is by its surroundings:
- //0.0 for "completely blocked by surrounding pixels,"
- //1.0 for "not occluded at all." The result is a grainy black and
- //white texture.
- //
- //Pass 3 is the final post-process where we multiply the diffuse
- //color from pass 1 with the occlusion value we get by averaging
- //the surrounding pixels of pass 2. (We could sample from pass 2's
- //texture directly, but that results in a very grainy look.)
- //////////////////////////////////////////////////////////////////////
- //
- //Model.cpp (or other objects' draw functions)
- //
- //Pass 1: Diffuse and Depth
- void Model::Draw()
- {
- //Hypothetical example - in reality, we'd batch draw calls
- //by shader to change GPU state as little as possible.
- BindBuffers( m_VBO, m_IBO );
- DrawIndicesWithTechnique( m_numVerts, m_numIndices,
- Shader* m_diffuse, 0, 0 );
- DrawIndicesWithTechnique( m_numVerts, m_numIndices,
- Shader* m_depth, 0, 0 );
- }
- //////////////////////////////////////////////////////////////////////
- //
- //Renderer.cpp
- //
- //Passes 2 and 3: Ambient Occlusion and Post-Processing
- void Renderer::Present(vec4 clearColor)
- {
- BindBuffers(m_fullscreenVBO, m_fullscreenIBO);
- //Pass 2: Ambient Occlusion
- SetRenderTarget(m_AmbientOcclusionTexture);
- //SI_TEXTURE_1 is diffuse from pass 1
- //SI_TEXTURE_2 is depth from pass 1
- ApplyTexture(SI_TEXTURE_3, m_randomNoiseTexture);
- DrawIndicesWithTechnique( 4, 6, m_AmbientOcclusionTechnique,
- 0, 0 );
- //Pass 3: Final post-process and output
- SetRenderTarget(m_PostProcessTexture);
- ApplyTexture(SI_TEXTURE_6, m_AmbientOcclusionTexture);
- DrawIndicesWithTechnique( 4, 6, m_PostProcessTechnique,
- 0, 0 );
- HRESULT errcheck = m_swapchain->Present(0, 0);
- CheckError(errcheck);
- ClearDepthBuffer();
- }
- //////////////////////////////////////////////////////////////////////
- //
- //shader.fx - HLSL version of code
- //
- ///////////////////////
- //Pass 1: Depth (and Diffuse, which isn't shown)
- struct VtoDepth
- {
- float4 pos:SV_POSITION;
- float4 worldpos:WORLDPOS;
- };
- void Depth_VS(
- float4 pos:POSITION,
- float4 tc:TEXCOORDS,
- out VtoDepth vtd)
- {
- vtd.pos = mul(pos, in_mvp);
- vtd.worldpos = pos;
- }
- float4 Depth_PS(VtoDepth vtd):SV_Target
- {
- return float4(length(in_camerapos.xyz - vtd.worldpos.xyz));
- }
- technique11 Depth
- {
- pass P0
- {
- SetVertexShader(CompileShader(vs_4_0, Depth_VS()));
- SetGeometryShader(NULL);
- SetPixelShader(CompileShader(ps_4_0, Depth_PS()));
- }
- }
- ///////////////////////
- //Pass 2: Ambient Occlusion
- struct VtoAmbientOcclusion
- {
- float4 pos:SV_POSITION;
- float4 tc:TEXCOORD;
- };
- void AmbientOcclusion_VS(
- float4 pos:POSITION,
- float4 normal:NORMAL,
- float4 tangent:TANGENT,
- float4 tc:TEXCOORD,
- out VtoAmbientOcclusion vtao)
- {
- vtao.pos = pos;
- vtao.tc = tc;
- }
- //rotating kernel - we combine this with random noise
- //to get a randomly distributed set of points around each pixel
- //to reduce banding
- static const float2 AO_SAMPLES[8] =
- {
- float2(-0.71, 0.71), float2(0, 1),
- float2(0.71, 0.71), float2(0, -1),
- float2(1, 0), float2(0.71, -0.71),
- float2(-1, 0), float2(-0.71, -0.71)
- };
- float4 AmbientOcclusion_PS(VtoAmbientOcclusion vtao):SV_Target
- {
- //currently bound to in_texture2: Random Noise
- //currently bound to in_texture3: Scene Depth
- float3 rand = normalize
- (in_texture2.Sample(ao, vtao.tc.xy).xyz) * 2.0 - 1.0;
- float thisPixelDepth = in_texture3.Sample(ao, vtao.tc.xy).w;
- float sum = 0.0;
- for(int i = 0; i < 8; ++i) //8 rings
- {
- for(int k = 0; k < 8; ++k) //8 points on that ring
- {
- float2 sampleUVs = vtao.tc.xy + (k / 8.0) * (AO_SAMPLES[k] + rand.xy) *
- float2( 1.0 / in_screenWidth,
- 1.0 / in_screenHeight );
- float samplePixelDepth =
- in_texture3.Sample(ao, sampleUVs).x;
- float delta =
- thisPixelDepth - samplePixelDepth;
- if( delta > 1.0 && delta < 10.0)
- {
- sum += 1.0;
- }
- }
- }
- //get % of surrounding pixels that occlude this one
- float occ = 1.0 - (sum / 64.0);
- return float4(occ, occ, occ, 1.0);
- }
- technique11 AmbientOcclusion
- {
- pass P0
- {
- SetVertexShader(CompileShader(vs_4_0, AmbientOcclusion_VS()));
- SetGeometryShader(NULL);
- SetPixelShader(CompileShader(ps_4_0, AmbientOcclusion_PS()));
- }
- }
- ///////////////////////
- //Pass 3: Final post-process and render
- struct VtoPostprocess
- {
- float4 pos:SV_POSITION;
- float4 tc:TEXCOORD;
- };
- void postprocessVS(
- float4 pos:POSITION,
- float4 tc:TEXCOORD,
- out VtoPostprocess vtpp)
- {
- vtpp.pos = pos;
- vtpp.tc = tc;
- }
- //lower = grainer, higher = smokier/smoother
- static const int SSAO_BLUR_AMOUNT = 8;
- float4 postprocessPS(VtoPostprocess vtpp):SV_Target
- {
- //currently bound to in_texture1: Diffuse map from pass 1
- //currently bound to in_texture6: Ambient Occlusion pass 2
- float4 sceneColor = in_texture1.Sample(defss, vtpp.tc.xy);
- sceneColor = toneMap(sceneColor, in_texture6.Sample(defss, float2(0.5, 0.5)));
- //get occlusion and blur from surrounding pixels
- //so that end result isn't grainy
- float occ = 0.0;
- for(int x = 0; x < SSAO_BLUR_AMOUNT; ++x)
- {
- for(int y = 0; y < SSAO_BLUR_AMOUNT; ++y)
- {
- occ += in_texture8.Sample(defss, vtpp.tc.xy, int2(x - SSAO_BLUR_AMOUNT * 0.5,
- y - SSAO_BLUR_AMOUNT * 0.5)).x;
- }
- }
- occ /= (SSAO_BLUR_AMOUNT * SSAO_BLUR_AMOUNT);
- return sceneColor * occ;
- }
- technique11 postprocess
- {
- pass P0
- {
- SetVertexShader(CompileShader(vs_4_0,
- postprocessVS()));
- SetGeometryShader(NULL);
- SetPixelShader(CompileShader(ps_4_0, postprocessPS()));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement