[XNA] Rendertarget - Depth Map

Für Fragen zu Grafik APIs wie DirectX und OpenGL sowie Shaderprogrammierung.
Antworten
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

[XNA] Rendertarget - Depth Map

Beitrag von RustySpoon »

Hallo Community,

ich habe ShadowMapping in XNA implementiert und seltsames Problem. Bei mir funktioniert soweit alles super (Windows Vista, Radeon X1700 Mobility) und bei einem Kumpel auch (Windows 7, Radeon X1600), bei allen andern leider nicht (alle Windows 7, Geforce 8600, Geforce 9600 und Radeon HD4850). Das Problem scheint zusein, dass die Tiefentextur nicht angelegt wird und damit funktioniert dann natürlich das Schattieren nicht. Wenn ich die Textur in eine Datei ausgebe ist sie dann auch einfach leer.

So erzeuge ich das Rendertarget. Hier hab ich schon alle möglichen Parameterkonstellationen durchprobiert und es können auch alle denkbaren Targets auf allen Testsystemen angelegt werden, also daran scheint es zumindest nicht zu hängen.

Code: Alles auswählen

shadowTarget = new RenderTarget2D(device, 2048, 2048, 1, SurfaceFormat.Single);
shadowDepthStencilBuffer = new DepthStencilBuffer(device, 2048, 2048, DepthFormat.Depth24Stencil8);
Und hier die entsprechenden Shader aus einem Effect-File, leider sind die Shader so minimal, dass es hier eigentlich auch keine Probleme geben kann.

Code: Alles auswählen

float4x4 World;
float4x4 LightViewProjection;

...

struct CreateShadowMap_VSOut
{
    float4 Position : POSITION;
    float Depth      : TEXCOORD0;
};

...

CreateShadowMap_VSOut CreateShadowMapVS(float4 position: POSITION)
{
    CreateShadowMap_VSOut output = (CreateShadowMap_VSOut)0;
    
    output.Position = mul(position, mul(World, LightViewProjection)); 
    output.Depth = output.Position.z / output.Position.w; 
       
    return output;
}

float4 CreateShadowMapPS(CreateShadowMap_VSOut input) : COLOR
{ 
    return float4(input.Depth, 0.0f, 0.0f, 0.0f);
}
Soviel Möglichkeiten, wo irgendetwas schrecklich schieflaufen könnte existieren ja gar nicht, dennoch bin ich nach nunmehr 3 Tagen rumprobieren kaum ein Stück weiter. Leider sind meine Testmöglichkeiten etwas eingeschränkt, da es wie gesagt bei mir selbst einwandfrei funktioniert. Sollte noch mehr Code, Screenshots oder Videos gewünscht sein, bitte fragen.

Schonmal vielen Dank fürs Lesen!
Zuletzt geändert von RustySpoon am 18.08.2010, 20:49, insgesamt 1-mal geändert.
Despotist
Establishment
Beiträge: 394
Registriert: 19.02.2008, 16:33

Re: [XNA] Rendertarget - Depth Map

Beitrag von Despotist »

Hab zwar keine Ahnung von ShadowMapping aber interessant wäre noch der Code wo du Rendertargets, Shader usw setzt.

Habe auch die Specs der Grafikkarten nicht im Kopf aber könnte es sein dass deine Shaderversion nicht unterstützt wird? Da die Grakas wos nicht läuft etwas älter scheinen.
Benutzeravatar
Krishty
Establishment
Beiträge: 8267
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: [XNA] Rendertarget - Depth Map

Beitrag von Krishty »

Wenn GeForce 8x/9x und Radeon HD 4xxx etwas älter scheinen, haben wir wohl ein paar Jahre übersprungen. Sie sind vorletzte Generation, also SM 4.0 bzw 4.1 und damit voller D3D-10- bzw. teils D3D-10.1-Support.

Gruß, Ky
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [XNA] Rendertarget - Depth Map

Beitrag von RustySpoon »

Hier setz ich das Rendertarget und render anschließend:

Code: Alles auswählen

        
        protected void DrawShadowMap()
        {
            shadowLight = new ShadowMapLightCamera();
            shadowLight.IncludedFrustum = new BoundingFrustum(Camera.View * Camera.Projection);
            shadowLight.LightDirection = LightDirection(daytime);

            DepthStencilBuffer oldBuffer = device.DepthStencilBuffer;

            device.SetRenderTarget(0, shadowTarget);
            device.DepthStencilBuffer = shadowDepthStencilBuffer;

            device.Clear(Color.White);

            DrawGround("CreateShadowMap");
            DrawModels("CreateShadowMap");
            
            device.SetRenderTarget(0, null);
            device.DepthStencilBuffer = oldBuffer;

            shadowMap = shadowTarget.GetTexture();
        }
Und das komplette Rendern der Objekte inklusive Setzen aller Effekt-Parameter sieht so aus:

Code: Alles auswählen

        protected void DrawModels(string technique)
        {
            BoundingBox frustumBox = BoundingBox.CreateFromPoints(
                        new BoundingFrustum(Camera.View * Camera.Projection).GetCorners());

            List<Level.ModelObject> models =
                new List<Level.ModelObject>(Level.Models.Find(frustumBox));

            foreach (Level.ModelObject obj in models)
            {
                if(obj.BoundingBox.Intersects(frustumBox))
                {
                    Matrix[] transforms = new Matrix[obj.Model.Bones.Count];
                    obj.Model.CopyAbsoluteBoneTransformsTo(transforms);
                    
                    foreach (ModelMesh mesh in obj.Model.Meshes)
                    {
                        foreach (Effect effect in mesh.Effects)
                        {         
                            effect.CurrentTechnique = effect.Techniques[technique];
                            effect.Parameters["ShadowMap"].SetValue(shadowMap);
                            effect.Parameters["Projection"].SetValue(Camera.Projection);
                            effect.Parameters["View"].SetValue(Camera.View);
                            effect.Parameters["World"].SetValue(transforms[mesh.ParentBone.Index] * obj.Transform);
                            effect.Parameters["LightDirection"].SetValue(Vector3.Zero);
                            effect.Parameters["LightViewProjection"].SetValue(shadowLight.View * shadowLight.Projection);
                            effect.Parameters["AmbientLight"].SetValue(AmbientLight(daytime));
                            effect.Parameters["LightIntensity"].SetValue(LightIntensity(daytime));
                        }

                        mesh.Draw();                 
                    }
                }
            }
        }
Und noch fix die Technik im Effect-File:

Code: Alles auswählen

technique CreateShadowMap
{
	pass Pass0
	{
		VertexShader = compile vs_3_0 CreateShadowMapVS();
		PixelShader = compile ps_3_0 CreateShadowMapPS();
	}
} 
Ich verwende das Shader-Model 3.0, was eigentlich nicht unbedingt nötig ist, aber ich hatte auch an der Stelle bisschen rumexperimentiert. Alle Grafikkarten sollten das beherrschen und seltsamerweise sind die Karten auf denen es funktioniert die deutlich Älteren (~4 Jahre).
Benutzeravatar
RustySpoon
Establishment
Beiträge: 298
Registriert: 17.03.2009, 13:59
Wohnort: Dresden

Re: [XNA] Rendertarget - Depth Map

Beitrag von RustySpoon »

Ich hab die Lösung durch rumprobieren gefunden. Es lag wie vermutet am Shader. Nun lyncht mich bitte nicht, aber es war natürlich nur eine Parametergeschichte. Der Pixelshader muss wie folgt aussehen (im Alpha-Kanal muss 1 zurückgegeben werden):
float4 CreateShadowMapPS(CreateShadowMap_VSOut input) : COLOR
{
return float4(input.Depth, 0.0f, 0.0f, 1.0f);
}
Damit funktioniert es zwar scheinbar, aber mir ist nicht klar warum, bzw. warum es auf manchen Grafikkarten auch mit 0 funktioniert. Vielleicht kann mir das ja einer der Cracks hier erklären? ;)
Benutzeravatar
Schrompf
Moderator
Beiträge: 4879
Registriert: 25.02.2009, 23:44
Benutzertext: Lernt nur selten dazu
Echter Name: Thomas Ziegenhagen
Wohnort: Dresden
Kontaktdaten:

Re: [XNA] Rendertarget - Depth Map

Beitrag von Schrompf »

Klingt, als hätte AlphaTest zugeschlagen.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Antworten