Seite 1 von 1

[DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 09:11
von beuschl
Hi

Hab wieder mal ein Problem mit meinem Deferred Renderer. Ich habe jetzt mal ein DirectionalLight implementiert welches auch meist richtig funktioniert. Nur bei manchen Kamerawinkel/stellungen habe ich irgendwie ein ziemlich komisches Verhalten des Lichts. Ich habe ein kurzes Video davon gemacht damit ihr sehen könnt was ich genau meine (ca 2,5 mb groß)

http://www.file-upload.net/download-189 ... r.wmv.html

Wie man im Video erkennen kann hat man bei manchen Kamerastellungen einen Specular Anteil vom licht der das Terrain überstrahlt und dann wieder ist dieses Specular Licht plötzlich wieder weg obwohl die Kamera nur minimal bewegt/rotiert wurde. Habe echt keine Idee wodurch dieses Verhalten ausgelöst wird. Ähnliches Problem hab ich bei meinem PointLight (geht noch nicht so 100%ig) Da wird bei manchen Kamerastellungen das Licht gerendert und dann verschwindet es plötzlich wenn die Kamera rotiert wird nur um später wieder aufzutauchen

Hoffe ich konnte einigermaßen erklären was ich meine

Hier mein Shader code vom Directional Light (Nachdem die Geometry gezeichnet wurde wird ein Full Screen Rechteck gezeichnet und an diesen Shader geschickt)

Code: Alles auswählen

float4 LightColor;
float4 LightDir;

//position of the camera, for specular light
float3 view_position; 

//this is used to compute the world-position
matrix InvertViewProjection; 


Texture2D colorMap; 
Texture2D normalMap;
Texture2D depthMap;


struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD0;
};

SamplerState samLinear2
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Clamp;
    AddressV = Clamp;
};


////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(float3 Pos : POSITION, float2 Tex :TEXCOORD)
{
	PS_INPUT psInput;

    psInput.Pos = float4(Pos,1);
    psInput.Tex = Tex;
    return psInput;
}

///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
float4 PS(PS_INPUT psInput) : SV_Target
{
    float4 normalData = normalMap.Sample(samLinear2, psInput.Tex);
    //tranform normal back into [-1,1] range
    float3 normal = 2.0f * normalData.xyz - 1.0f;
    //get specular power, and get it into [0,255] range]
    float specularPower = normalData.a * 255;
    //get specular intensity from the colorMap
    float specularIntensity = colorMap.Sample(samLinear2, psInput.Tex).a;
	
	   //read depth
    float depthVal = depthMap.Sample(samLinear2, psInput.Tex).r;
        
    //compute screen-space position
    float4 position;
    position.x = psInput.Tex.x * 2.0f - 1.0f;
    position.y = -(psInput.Tex.x * 2.0f - 1.0f);
    position.z = depthVal;
    position.w = 1.0f;
        
    //transform to world space
    position = mul(position, InvertViewProjection);
    position /= position.w;
	
	
	float3 nLightDirection = normalize(LightDir);
	float3 directionToCamera = normalize(view_position - position);

	// Lichtanteil Directional berechnen
	float4 I_Directional = min(saturate(dot(normalize(normal), nLightDirection)), 1.0f);

	// Sepcular Directional Werte berechnen
	float3 Reflect_Directional = normalize(2*I_Directional*normal - nLightDirection);
	float4 Specular_Directional = pow(saturate(dot(Reflect_Directional, directionToCamera)), 16);

	float DiffuseAttn = clamp(0, 1, dot(normal, LightDir));

	return LightColor*(I_Directional*(Specular_Directional+DiffuseAttn));
}

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 09:46
von Zudomon
float4 I_Directional = min(saturate(dot(normalize(normal), nLightDirection)), 1.0f);
=>
float4 I_Directional = max(dot(normalize(normal), nLightDirection), 0.0f);

float3 directionToCamera = normalize(view_position - position);
=>
float3 directionToCamera = normalize(position - view_position);

float3 Reflect_Directional = normalize(2*I_Directional*normal - nLightDirection);
=>
float3 Reflect_Directional = normalize(reflect(directionToCamera, normal));

float4 Specular_Directional = pow(saturate(dot(Reflect_Directional, directionToCamera)), 16);
=>
float4 Specular_Directional = pow(max(dot(Reflect_Directional, nLightDirection), 0.0f), 16);

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 13:34
von Krishty
Warum max(x, 0.0f) statt saturate(x) mit -1 <= x <= +1?

Gruß, Ky

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 15:05
von beuschl
ich hab den Light Shader jetzt mal angepasst aber eine wirkliche Veränderung merk ich irgendwie nicht. Hier ein neues Video wies jetzt aktuell aussieht (irgendwie wirkt das ganze für mich nicht "richtig")

http://www.file-upload.net/download-190 ... 2.wmv.html


Ich hab zusätzlich noch ein weiteres Video gemacht bei dem ich 8 Directional Lights verwende (verschiedene Farben+Richtungen) da man ab ca 8 Lights einen weiteren Fehler bemerken kann. Die Flächen rund ums Terrain die schwarz sind, sollten eigentlich blaues Wasser sein. Und in dem Video kann man sehen das bei einem bestimmen Kamerawinkel ein kleiner Teil vom Wasser beleuchtet wird und dann wieder nicht. Weiss aber nicht ob das irgendwie mit dem oben beschriebenen Problem zusammenhängt, aber irgendwie kommt mir dieses Problem sehr ähnlich mit dem anderen vor

http://www.file-upload.net/download-190 ... 3.wmv.html

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 17:00
von Zudomon
@Krishty
könnte man auch machen, wobei saturate von 0 bis 1 geht, nicht von -1 bis 1. Hauptsache es wird das negative Licht rausgeschmissen. Ich habe mir das max angewöhnt, wenn damit ich sicher gehe, dass nicht versehentlich auch von oben abschnitten wird. Aber beim Skalarprodukt ist es ja eh egal, weils ja 1 nicht überschreitet.

@beschl
also beim ersten Video sieht das korrekt aus. Das sich das Spekulare ändert, liegt ja daran, dass es eine Reflektion ist. Was mich sehr irritiert ist das abgeschnittene Licht. Du darfst das Licht keinesfalls abschneiden, kann natürlich auch daran liegen, dass du die Lichtinformation in ein Target renderst (und dieses auch weiterverwendest), indem die Helligkeitswerte verloren gehen. Ansonsten wurden hier ja schon oft über HDR geredet, da dann nochmal schauen. Kannst auch nochmal den aktuellen Shader posten, vielleicht ist da noch der eine oder andere Fehler drin.

Was das Wasser angeht, da sieht es so aus, als ob da nur das spekulare Licht von einer direktionalen Lichtquelle drauf angewendet wird. Mehr kann ich dazu leider nicht sagen, dafür müsste man das genauer untersuchen.

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 17:23
von Krishty
Zudomon hat geschrieben:Ich habe mir das max angewöhnt, wenn damit ich sicher gehe, dass nicht versehentlich auch von oben abschnitten wird. Aber beim Skalarprodukt ist es ja eh egal, weils ja 1 nicht überschreitet.
Okay … in dem Fall ist saturate() zu bevorzugen, weil es – im Gegensatz zu max() – kostenlos ist. Nur als kleine Klugscheißerei am Rande :D

Re: [DX10] Problem mit Deferred Light

Verfasst: 20.09.2009, 17:26
von Zudomon
Krishty hat geschrieben:
Zudomon hat geschrieben:Ich habe mir das max angewöhnt, wenn damit ich sicher gehe, dass nicht versehentlich auch von oben abschnitten wird. Aber beim Skalarprodukt ist es ja eh egal, weils ja 1 nicht überschreitet.
Okay … in dem Fall ist saturate() zu bevorzugen, weil es – im Gegensatz zu max() – kostenlos ist. Nur als kleine Klugscheißerei am Rande :D
Dann ist es mir natürlich nicht egal... wusste nicht, dass saturate() gratis ist... danke für den Tipp :D

Re: [DX10] Problem mit Deferred Light

Verfasst: 21.09.2009, 08:25
von beuschl
ok danke schonmal für die Hilfe. Der Fehler lag bei mir weil ich Trottl im FX Composer noch die alte Shader Datei bearbeitet habe, die im aktuellen Projekt nicht mehr verwendet wird! Das Ergebnis sieht jetzt aufjedenfall viel besser aus und wirkt bei ebstimmten kamerawinkeln nicht mehr so abgeschnitten wie noch in dem Video zuvor!

Wegden dem Wasser: für die Lichtberechnung nehm ich den gleichen Shader wie fürs Terrain. Also eben das DirectionalLight. Das Wasser ist jetzt noch imemr schwarz. Was merkwürdig ist, ist wie gesagt, dass ich erst bei viele Lichtquellen (s0 ab 7-8) dieses Effekt habe wie im Video 3. Also das ich da ganz wenig vom Wasser sehen kann. Habe ich nur zb 3 DirectionalLight Lichtquellen bleibt das Wasser immer und überall schwarz.

Render ich das Wasser ohne dem Terrain kann ich das komplette Wasser sehen. Ich setze allerdings zwischen den beiden draw Calls keinerlei RenderStates, Blendstates etc sondern zeichne nach dem Wasser einfach das Terrain drüber
Was ich in PIX gesehen habe und mich sehr irritiert ist, dass im Nomral RT genau dort wo das Wasser ist alles grau ist (ClearFarbe des Rendertargets) also keine Normalen eingetragen sind (dadurch bekommen diese Stellen wohl beim Light RT kein Licht ab und sind dann schwarz) Zeichne ich das Wasser aber alleine ohne Terrain sind im Normal RT Normalen fürs Wasser drinnen!

Hier ein Bild vom ColorRT und Normal RT zum veranschaulichen des Ganzen

http://s4.directupload.net/file/d/1924/7eb4ev48_jpg.htm

Im Shader der das Wasser zeichnet mach ich eigentlich genau das gleiche wie im Shader der das Terrain zeichnet.
Hier das Codestück was die Normalen betrifft

Code: Alles auswählen

// Im VertexShader mach ich das:
	psInput.Norm = normalize(mul(Norm, (float3x3)World));

// Im PixelShader das hier (output.Norm ist float4 Norm : SV_TARGET1; )
    output.Norm.rgb = 0.5f * (psInput.Norm + 1.0f); 
    output.Norm.a = specularPower;