Jump to content

  • Log In with Google      Sign In   
  • Create Account

Lotes

Member Since 08 Nov 2012
Offline Last Active Dec 11 2014 05:12 AM

#5192070 Problems with Alchemy SSAO implementation

Posted by Lotes on 10 November 2014 - 09:41 AM

I finally fixed it :-). The view space position was not computed correctly. And the disk radius was wrong. Screenshot appended...

//from: http://graphics.cs.williams.edu/papers/AlchemyHPG11/

#define PI 3.14159265

//Important: http://msdn.microsoft.com/en-us/library/bb509632%28v=vs.85%29.aspx
cbuffer ConstBuffer : register(c0)
{
	float4x4 inverseProjection;
	float cameraFOV;	
    float cameraZNear;
	float cameraZFar;	
	float width; 
    float height;    
}

static const float halfFOV = cameraFOV / 2;

static const int samplesCount = 16;
static const int spiralTurns = 10;

static const float radius = 0.10;
static const float beta = 0.2;
static const float epsilon = 0.01;

Texture2D normalDepthTexture: register(t0);

SamplerState textureSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VS_INPUT
{
    float3 position             : POSITION;    
    float3 normal               : NORMAL;
    float2 uv                   : TEXCOORD;
};

struct VS_OUTPUT
{
    float4 position             : SV_POSITION;
    float2 uv                   : TEXCOORD;
};

VS_OUTPUT VShader(VS_INPUT i)
{
    VS_OUTPUT vo;    
    vo.position = float4(i.position, 1);    
    vo.uv = i.uv;
    return vo;
}

float4 readNormalDepth(float2 uv)
{
    return normalDepthTexture.SampleLevel(textureSampler, uv, 0.0f);
}

float3 readNormal(float2 uv)
{
    return (readNormalDepth(uv).xyz - 0.5) * 2;
}

float readDepth(float2 uv)
{
    return readNormalDepth(uv).a;
}

float linearDepth(float d)
{
	//http://www.humus.name/temp/Linearize%20depth.txt
	//returns a value between 0 (near) and 1 (far)
	return d / (cameraZFar - d * (cameraZFar - cameraZNear));
}

float3 getViewPosition(float2 uv)
{
	float depth = readDepth(uv);
	float4 screenCoordinate = 2 * (float4(uv.x, 1-uv.y, depth, 1) - 0.5);
	float4 viewCoordinate = mul(inverseProjection, screenCoordinate);
	return viewCoordinate.xyz / viewCoordinate.w;
}

float3 getPosition(float2 uv)
{
	return getViewPosition(uv);
}

float2 tapLocation(int sampleNumber, float spinAngle)
{
	float alpha = float(sampleNumber + 0.5) * (1.0 / samplesCount);
	float angle = alpha * (spiralTurns * 2 * PI) + spinAngle;
	float radius = alpha;
	return radius * float2(cos(angle), sin(angle));
}

float4 PShader(VS_OUTPUT i) : SV_Target
{   	
	float ao = 0;
	float3 currentPoint = getPosition(i.uv);
	float currentDepth = linearDepth(readDepth(i.uv));
	float3 normal = readNormal(i.uv);
	float2 pixelPosition = i.uv * float2(width, height);
	float random = (3*int(pixelPosition.x)^int(pixelPosition.y)+int(pixelPosition.x)*int(pixelPosition.y))*10.0;
	float diskRadius = radius / (2 * (currentDepth * (cameraZFar - cameraZNear) + cameraZNear) * tan(halfFOV));
	[unroll]
	for(int sampleIndex=0; sampleIndex < samplesCount; sampleIndex++)
	{
		float2 offset = tapLocation(sampleIndex, random);
		float2 samplePosition = i.uv + diskRadius * offset;
		float3 samplePoint = getPosition(samplePosition);
		float3 v = samplePoint - currentPoint;
		float vv = dot(v, v);
		float vn = dot(v, normal);
		if(currentDepth < 1) //do not AO for far plane
			ao += max(0, vn + currentDepth * 0.001) / (vv + epsilon);
	}
	ao *= 2.0 * PI * radius * beta / samplesCount;
	ao = min(1, max(0, 1 - ao));
	return float4(ao, ao, ao, 1);	
}

Attached Thumbnails

  • ssao.png



PARTNERS