Seite 1 von 1

[XNA] Rendertarget - Depth Map

Verfasst: 18.08.2010, 19:56
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!

Re: [XNA] Rendertarget - Depth Map

Verfasst: 18.08.2010, 20:34
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.

Re: [XNA] Rendertarget - Depth Map

Verfasst: 18.08.2010, 20:43
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

Re: [XNA] Rendertarget - Depth Map

Verfasst: 18.08.2010, 20:44
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).

Re: [XNA] Rendertarget - Depth Map

Verfasst: 19.08.2010, 23:35
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? ;)

Re: [XNA] Rendertarget - Depth Map

Verfasst: 20.08.2010, 08:14
von Schrompf
Klingt, als hätte AlphaTest zugeschlagen.