ogre-ssao / media / ssao / crytek / crytek_ssao.cg

struct AppData
{
    float4 p   : POSITION;
    float3 n   : NORMAL;
    float2 uv  : TEXCOORD0;
};

struct VertexOut
{
    float4 p             : POSITION;
    float2 pixelPos      : TEXCOORD0;
};

struct FragmentInput
{
    float2 pixelPos      : TEXCOORD0;
};

//------------------------------------------------------------------------------
VertexOut crytek_ssao_vs(AppData IN, uniform float4x4 wvp, uniform float3 farCorner)
{
    VertexOut OUT;
    OUT.p = mul(wvp, IN.p);

    // clean up inaccuracies for the UV coords
    float2 uv = sign(IN.p.xy);
    // convert to image space
    uv = (float2(uv.x, -uv.y) + 1.0) * 0.5;
    OUT.pixelPos = uv;
    
	return OUT;
}



#define PI 3.141592653


void crytek_ssao_ps(FragmentInput IN
    ,uniform float far
    ,uniform sampler2D geomMap : TEXUNIT0
	,uniform sampler2D randMap : TEXUNIT1
	,uniform float4 cViewportSize
    ,uniform float nearClipDistance
	,uniform float farClipDistance
    ,uniform float cFov
	,uniform float cSampleInScreenSpace // whether to sample in screen or world space
	,uniform float cSampleLengthScreenSpace // The sample length in screen space [0, 1]
	,uniform float cSampleLengthWorldSpace // the sample length in world space in units
	,uniform float cOffsetScale // [0, 1] The distance of the first sample. samples are the 
								// placed in [cOffsetScale * cSampleLengthScreenSpace, cSampleLengthScreenSpace]
	,uniform float cDefaultAccessibility // the default value used in the lerp() expression for invalid samples [0, 1]
	,uniform float cEdgeHighlight // multiplicator for edge highlighting in [1, 2] 1 is full hightlighting 2 is off
    ,out float4 oColor)
{

	const int nSampleNum = 32; // number of samples

	// compute the distance between the clipping planes to convert [0, 1] depth to world space units
	const float clipDepth = farClipDistance - nearClipDistance;

	// get the depth of the current pixel and convert into world space unit [0, inf]
	float fragmentWorldDepth = tex2D(geomMap, IN.pixelPos).r * clipDepth;

	// get rotation vector, rotation is tiled every 4 screen pixels
	float2 rotationTC = IN.pixelPos * cViewportSize.xy / 4;
	float3 rotationVector = 2 * tex2D(randMap, rotationTC).xyz - 1; // [-1, 1]x[-1. 1]x[-1. 1]
	
	float rUV = 0; // radius of influence in screen space
	float r = 0; // radius of influence in world space
	if (cSampleInScreenSpace == 1)
	{
		rUV = cSampleLengthScreenSpace;
		r = tan(rUV * cFov) * fragmentWorldDepth;
	}
	else
	{
		rUV = atan(cSampleLengthWorldSpace / fragmentWorldDepth) / cFov; // the radius of influence projected into screen space
		r = cSampleLengthWorldSpace;
	}

	float sampleLength = cOffsetScale; // the offset for the first sample
	const float sampleLengthStep = pow((rUV / sampleLength), 1.0f/nSampleNum);
	
	float accessibility = 0;


	float3 sphereVectors[8] = {
		float3(-1, -1, -1),
		float3(-1, -1, 1),
		float3(-1, 1, -1),
		float3(-1, 1, 1),
		float3(1, -1, -1),
		float3(1, -1, 1),
		float3(1, 1, -1),
		float3(1, 1, 1)
	};


	// sample the sphere and accumulate acessability
	for (int i = 0; i < (nSampleNum/8); i++)
	{
			//generate offset vector
			float3 offset = normalize(sphereVectors[i]) * sampleLength;
			
			// update sample length
			sampleLength *= sampleLengthStep;
		
			// reflect offset vector by random rotation sample (i.e. rotating it) 
			float3 rotatedOffset = reflect(offset, rotationVector);
					
			float2 sampleTC = IN.pixelPos + rotatedOffset.xy * rUV;
				
			// read scene depth at sampling point and convert into world space units (m or whatever)
			float sampleWorldDepth = tex2D(geomMap, sampleTC).r * clipDepth;
			//float sampleWorldDepth = 0.005f * clipDepth;			

			// check if depths of both pixles are close enough and sampling point should affect our center pixel
			float fRangeIsInvalid = saturate((fragmentWorldDepth - sampleWorldDepth) / r);
			
			// accumulate accessibility, use default value of 0.5 if right computations are not possible
			accessibility += lerp(sampleWorldDepth > (fragmentWorldDepth + rotatedOffset.z * r), cDefaultAccessibility, fRangeIsInvalid);

			//accessibility += abs(sampleWorldDepth - fragmentWorldDepth);

//			accessibility += (sampleWorldDepth > (fragmentWorldDepth + rotatedOffset.z * r)) + (fRangeIsInvalid);
//			accessibility += fRangeIsInvalid;

	}
	
	// get average value
	accessibility /= nSampleNum;

	// normalize, remove edge hightlighting
	accessibility *= cEdgeHighlight;
	
	// amplify and saturate if necessary
	oColor = float4(accessibility.xxx, 1);




}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.