SSAO Probleme

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

SSAO Probleme

Beitrag von MadMax »

Hallo zusammen,

ich versuche jetzt schon einige Zeit eine vernünftige SSAO Implementierung hinzubekommen aber scheitere immer wieder. Anbei der Code von meinem letzten Versuch(nach http://john-chapman-graphics.blogspot.d ... orial.html). Die Eingabedaten sind im World Space:

Code: Alles auswählen

struct VS_OUTPUT
{
    float4  position   : SV_Position;   
    float2  tex0       : TEXCOORD0;
	float3  pos        : TEXCOORD1;
    float3  norm       : TEXCOORD2;
	float3  color      : TEXCOORD3;
};

struct PS_OUTPUT
{
    float4 RGBColor : SV_Target;    
};

cbuffer MATRIXBUFFER
{
	matrix CAMERA_MATRIX;
	matrix DEVICE_MATRIX;
	matrix INVERT_CAMERA_MATRIX;
	matrix INVERT_DEVICE_MATRIX;
};

cbuffer APPLICATIONBUFFER
{
	float4 APPLICATION_MATERIAL;
};


Texture2D<float4> RENDERTARGET_1; 
Texture2D<float4> RENDERTARGET_2; 
Texture2D<float4> RENDERTARGET_3; 
Texture2DMS<float,8>  ZBUFFER;
Texture2D<float4> RANDOM;

SamplerState g_samPoint
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = MIRROR;
    AddressV = MIRROR;
	AddressW = MIRROR;
};

float SampleDepth(float2 uv)
{
	int2 size = int2(1344,730);
	int2 index = int2(uv.x*size.x,uv.y*size.y);
	return ZBUFFER.Load(int3(index, 0), 0 );
}

float3 SampleNormal(float2 uv)
{
	return normalize(RENDERTARGET_2.Sample(g_samPoint,uv.xy).xyz);
}

float3 SamplePos(float2 uv)
{
	return RENDERTARGET_3.Sample(g_samPoint,uv.xy);
	//Alternative aber mit gleichem Ergebniss
        float3 screenPos; 
	float2 uvPos=uv;
		uvPos.y = 1-uvPos.y;
	uvPos = uvPos*2.0-1.0;
	screenPos = float3(uv, SampleDepth(uv)); 
	float4 worldPos = mul(float4(screenPos, 1.0f), INVERT_DEVICE_MATRIX);
		worldPos = mul(float4(screenPos, 1.0f), INVERT_CAMERA_MATRIX);
		worldPos.xyz /= worldPos.w;
	return worldPos.xyz;
}

float3 SampleColor(float2 uv)
{
	return RENDERTARGET_1.Sample(g_samPoint,uv.xy);
}

float3 SampleRandom(float2 uv)
{
	return normalize(RANDOM.Sample(g_samPoint,uv*float2(1344.0,730.0)*1.0/64).xyz*2.0 - float3(1.0,1.0,1.0));
}

float SSAO3(float2 uv)
{
	float SSAORad=1.0*APPLICATION_MATERIAL.x;
	

	float3 samples[16] = {
		float3(-0.0182121,0.197594,0.232228),
		float3(0.293952,-0.0652266,0.250021),
		float3(-0.104782,-0.463961,0.511148),
		float3(0.12743,0.0689862,0.118884),
		float3(0.0883658,1.01601,0.897755),
		float3(-0.0711823,0.0184628,0.0630255),
		float3(0.399123,-0.0238302,0.260211),
		float3(0.246834,-0.400789,0.305677),
		float3(-0.965089,-1.07855,1.23738),
		float3(-0.114554,-0.124242,0.146548),
		float3(0.619386,-0.564064,0.434935),
		float3(0.739393,0.396969,0.642246),
		float3(-0.0852846,-0.327954,0.153502),
		float3(0.209668,-0.237002,0.0298241),
		float3(0.00607007,0.0817364,0.160404),
		float3(0.00546413,0.00826584,0.00676915)
	};


	float3 random = SampleRandom(uv);
	float3 currentPixelNormal = SampleNormal(uv);
	float3 currentPixelPos = SamplePos(uv);

	float3 rvec = normalize(float3(random.xy,0.0));
	float3 tangent = normalize(rvec - currentPixelNormal * dot(rvec, currentPixelNormal));
	float3 bitangent = cross(currentPixelNormal, tangent);
	float3x3 tbn = float3x3(tangent, bitangent, currentPixelNormal);


	int iterations = 16;

	float ao = 0.0;
	for (int i = 0; i < iterations; ++i) {
		// get sample position:
		float3 sample = mul(samples[i],tbn);
		sample = sample * SSAORad + currentPixelPos;
  
		// project sample position:
		float4 offset = float4(sample, 1.0);
		offset = mul(offset,CAMERA_MATRIX);
		offset = mul(offset,DEVICE_MATRIX);
		offset.xy /= offset.w;
		offset.xy = offset.xy * 0.5 + 0.5;
  
		// get sample depth:
		float sampleDepth = SamplePos(uv).z;
  
		// range check & accumulate:
		float rangeCheck= abs(currentPixelPos.z - sampleDepth) < SSAORad ? 1.0 : 0.0;
		ao += (sampleDepth <= sample.z ? 1.0 : 0.0) * rangeCheck;
	}	
	return  ao =  (ao / iterations);   
}

float4 main(VS_OUTPUT frag) : SV_Target
{
	float  depth = SampleDepth(frag.tex0);
	float3 norm  = SampleNormal(frag.tex0);
	float  ao=SSAO3(frag.tex0);
	
	return float4(ao,ao,ao,1.0);
	//return float4(SampleNormal(frag.tex0),1.0);
	//return float4(SampleColor(frag.tex0)-ao,1.0);
}

Und so sieht das ganze aus:

Bild

<a%20href="http://www.imgbox.de/"%20title="Bilder% ... er="0"></a>

Hatt jemand eine Idee was ich falsch mache?

PS: Ich habe mal SamplePos umgeschrieben das da immer 0 oder ein konstanter Vektor rauskommt aber das ändert gar nix am Ergebnis :shock:
Zuletzt geändert von MadMax am 08.09.2013, 17:58, insgesamt 1-mal geändert.
Benutzeravatar
Schrompf
Moderator
Beiträge: 4855
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: SSAO Probleme

Beitrag von Schrompf »

Das Bild wird leider nicht angezeigt.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

Jetzt aber :-)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: SSAO Probleme

Beitrag von CodingCat »

Deine Zufallstextur wird schonmal nicht wiederholt, wie auf dem Bild unschwer zu erkennen. Also entsprechenden Sampler State auf Repeat stellen. Die Angaben im HLSL-Sampler-Block sind ausserhalb des fuer deprecated erklaerten Effects11-Frameworks wirkungslos, d.h. du musst haendisch einen entsprechenden Sampler State Block mittels PSSetSamplers in den richtigen Slot setzen. Es ist uebrigens ratsam, die Zufallstextur exakt pixelweise auf den Bildschirm abzubilden.

Ansonsten einfach mal mittels Farbkodierung debuggen, wo da was rauskommt, und wieso bestimmte Dinge sich nicht oder falsch aufs Ergebnis auswirken.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

Danke! Das mit dem Sampler States hatte ich so noch nicht gewusst. Was die RND-Textur angeht verwende ich jetzt einen in der gleichen Größe wie mein Bildschirm ich denke das hast du mit exakt Pixelweise gemein oder?

Ich habe noch einige kleine Fehler gefixed aber es sieht immer noch völlig falsch aus:

Im View Space
Bild

Im World Space
Bild

Neuer Code:

Code: Alles auswählen

float SSAO3(float2 uv)
{
	float SSAORad=1.0*APPLICATION_MATERIAL.x;
	

	float3 samples[36] = {
		float3(-0.0182121,0.197594,0.232228),
		float3(0.293952,-0.0652266,0.250021),
		float3(-0.104782,-0.463961,0.511148),
		float3(0.12743,0.0689862,0.118884),
		float3(0.0883658,1.01601,0.897755),
		float3(-0.0711823,0.0184628,0.0630255),
		float3(0.399123,-0.0238302,0.260211),
		float3(0.246834,-0.400789,0.305677),
		float3(-0.965089,-1.07855,1.23738),
		float3(-0.114554,-0.124242,0.146548),
		float3(0.619386,-0.564064,0.434935),
		float3(0.739393,0.396969,0.642246),
		float3(-0.0852846,-0.327954,0.153502),
		float3(0.209668,-0.237002,0.0298241),
		float3(0.00607007,0.0817364,0.160404),
		float3(0.00546413,0.00826584,0.00676915),
		float3(0.0266294,0.0466458,0.0651193),  float3(-0.00876011,0.491309,0.315298),float3(-0.410571,-0.862981,0.896798),   float3(-0.169266,0.428677,0.164507),
		float3(0.011676,0.167468,0.100763),     float3(0.128002,0.0476439,0.527884),  float3(0.452763,-0.00383817,0.276509),  float3(-0.609517,0.434583,0.679426),
		float3(-0.00927132,0.0164443,0.0726412),float3(-0.0419945,0.144547,0.219946), float3(0.628496,0.612039,0.0667422),    float3(0.0205594,0.010582,0.0135621),
		float3(-0.034159,-0.0483252,0.0285935), float3(0.372881,-0.237748,0.247605),  float3(-0.0245225,0.00747819,0.0225939),float3(-0.0931879,0.239895,0.100817),
		float3(0.219383,0.210142,0.170228),     float3(0.115573,0.0519275,0.011864),  float3(0.105376,0.0526046,0.261525),    float3(-0.150244,-0.045597,0.153778)
};


	float3 random = SampleRandom(uv);
	float3 currentPixelNormal = SampleNormal(uv);
	float3 currentPixelPos = SamplePos(uv);

	float3 rvec = normalize(float3(random.xy,0.0));
	float3 tangent = normalize(rvec - currentPixelNormal * dot(rvec, currentPixelNormal));
	float3 bitangent = cross(currentPixelNormal, tangent);
	float3x3 tbn = float3x3(tangent, bitangent, currentPixelNormal);


	int iterations = 36;

	float ao = 0.0;
	for (int i = 0; i < iterations; i+=1) {
		// get sample position:
		float3 sample = mul(samples[i],tbn);
		sample = sample * SSAORad + currentPixelPos;
  
		// project sample position:
		float4 offset = float4(sample, 1.0);
		offset = mul(offset,CAMERA_MATRIX);
		offset = mul(offset,DEVICE_MATRIX);
		offset.xy /= offset.w;
		offset.xy = offset.xy * 0.5 + 0.5;
  
		// get sample depth:
		float sampleDepth = SamplePos(offset).z;
  
		// range check & accumulate:
		float rangeCheck= abs(currentPixelPos.z - sampleDepth) < SSAORad ? 1.0 : 0.0;
		ao += (sampleDepth <= sample.z ? 1.0 : 0.0) * rangeCheck;
	}	
	return  ao =  (ao / iterations);   
}
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

Ach ja so sample ich meine RND-Vectoren:

float3 SampleRandom(float2 uv)
{

float sizeX=1344.0;
float sizeY=730.0;
float bit=255.0;

float2 uvR=uv;
uvR.x *= 1344.0/sizeX;
uvR.y *= 730.0/sizeY;

float3 rand=RANDOM.Sample(PointSamplerWrap,uvR).xyz*(1.0/bit); //RAND VEC [0..1]
rand=float3(rand.xy,0.0); //RAND VEC Z=0
rand=rand*2.0-float3(1.0,1.0,0.0); //RAND VEC [-1..1]

return normalize(rand);
}

Sobald ich bit auf 1.0 setze bekomme ich das folgende Bild:
Bild
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: SSAO Probleme

Beitrag von CodingCat »

MadMax hat geschrieben:Danke! Das mit dem Sampler States hatte ich so noch nicht gewusst. Was die RND-Textur angeht verwende ich jetzt einen in der gleichen Größe wie mein Bildschirm ich denke das hast du mit exakt Pixelweise gemein oder?
Nein, ich meinte nur, dass du die Zufallstextur genau so oft wiederholen solltest, dass ein Pixel in der Zufallstextur genauso groß ist wie ein Bildschirmpixel. Mit bildschirmfuellenden Noise-Texturen habe ich keine guten Erfahrungen gemacht. Insbesondere wenn die Verteilung nicht optimal ist, laesst sich das Rauschen hinterher kaum noch rausglätten. Lieber eine wiederholte Noise-Textur im Rahmen der Größe des Glättungskernels.

Dass du mit Skalierung 1/255 nichts siehst, ist kein Wunder, weil dir Sample() ziemlich sicher Werte zwischen 0 und 1 liefert. Das verrauschte Ergebnis ist aber in der Tat immer noch weit von plausibler Ambient Occlusion weg, weiter debuggen! ;)
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

die Skalierung ist jetzt weg :-)
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

So habe mal als debbuged:

Noise:
Bild

Noise abs:
Bild

World Color:
Bild

World Normal:
Bild

World Position:
Bild

World AO:
Bild

View Color:
Bild

View Normal:
Bild

View Position:
Bild

View AO:
Bild
Benutzeravatar
Blue Cobold
Beiträge: 58
Registriert: 13.06.2001, 00:00
Kontaktdaten:

Re: SSAO Probleme

Beitrag von Blue Cobold »

Die Normals sehen merkwürdig aus, speziell an den glatten Wand-Teilen über den Säulen.
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

Ja dachte ich auch zuerst liegt aber denke ich an der Datei.

Andere Szene:
Bild

Ich habe eher das Gefühl das es irgendwo an den Koordinatensystemen liegt. Ich verwende übrigens ein linkshändiges. Kann mir jemand sagen ob ich dazu die Schritte im Tutorial irgendwie anpassen muss? Habe zwar schon ein bisschen rumprobiert aber das Ergebnis wird nicht besser.
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

Wichtiger Bugfix:

//project sample position:
float4 offset = float4(sample, 1.0);
if(APPLICATION_MATERIAL.z == 1.0){
offset = mul(offset,CAMERA_MATRIX);}
offset = mul(offset,DEVICE_MATRIX);
offset.y *= -1.0;
offset.xy /= offset.w;
offset.xy = offset.xy * 0.5 + 0.5;

Im Viewspace sieht das ganze jetzt schon etwas besser aus:

Bild
MadMax
Beiträge: 59
Registriert: 24.01.2003, 13:31
Kontaktdaten:

Re: SSAO Probleme

Beitrag von MadMax »

So langsam wirds:

ohne SSAO
Bild

mit SSAO
Bild
Benutzeravatar
TGGC
Establishment
Beiträge: 569
Registriert: 15.05.2009, 18:14
Benutzertext: Ich _bin_ es.
Alter Benutzername: TGGC
Echter Name: Ich _bin_ es.
Wohnort: Mainz
Kontaktdaten:

Re: SSAO Probleme

Beitrag von TGGC »

Ich glaube auch, das in der anderen Szene die Normalen falsch berechnet werden. Als waere alles in einer Smoothgroup.
Antworten