4
\$\begingroup\$

UPDATE: See photos below the description

I try desperately to implement shadows on my XNA games. My game is a style of games like Voxel (minecraft).

The problem is that I do not find support / help or example explaining how to add shadows on cubes (vertices and indices) with (BasicEffect). I just find examples to add shadows with a (HLSL Effect) or a "Model".

Is it possible to create shadows with the class "BasicEffect" on vertices cube ? I already try with "Matrix.CreateShadow(...)" but no success .

I really hope so.

The logic of my function "DrawWorld":

#region DrawWorld
    // Draw all cubes in the world
    public void DrawWorld(GameTime gameTime)
    {
        effet.TextureEnabled = true;
        Plane lightPlane = new Plane(Vector3.UnitY, 0);
        Vector3 lightPos = new Vector3(-10f, 10f, 10f);

        //Try to initialize shadowMatrix
        Matrix shadowMatrix = Matrix.CreateShadow(Vector3.Normalize(lightPos), lightPlane);   

        // Light settings
        effet.LightingEnabled = true;
        effet.DirectionalLight0.Enabled = true;
        effet.DirectionalLight1.Enabled = true;
        effet.DirectionalLight2.Enabled = true;
        effet.DirectionalLight0.DiffuseColor = col.ToVector3();

        effet.SpecularPower = 512f;

        // Fog settings
        effet.FogEnabled = true;
        effet.FogStart = arcadia.camera.NearPlane;
        effet.FogEnd = arcadia.camera.FarPlane;
        effet.FogColor = Microsoft.Xna.Framework.Color.White.ToVector3();

        // Set World with shadow matrice 
        effet.World = Matrix.Identity * shadowMatrix  ;
        effet.View = arcadia.camera.View;
        effet.Projection = arcadia.camera.Projection;

        // Set the cube vertexBuffer and indice
        arcadia.Game.GraphicsDevice.SetVertexBuffer(graphicData[regionIndex][a].VertexBuffer);
        arcadia.Game.GraphicsDevice.Indices = graphicData[regionIndex][a].IndexBuffer;

        // Apply the basic effect
        effet.CurrentTechnique.Passes[0].Apply();


        // Draw the cubes vertices
        arcadia.Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, graphicData[regionIndex][a].VertexPosition.Length, 0, graphicData[regionIndex][a].Indices.Length / 3);


    }
    // #END OF DRAWWORLD
    #endregion

Without shadow is this : enter image description here

When i try to add shadow with "Matrix.CreateShadow(...)" i got this bad result: enter image description here

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Shadows are usually drawn by first rendering the scene to a RenderTarget (which you can use your BasicEffect for) to get both depth and color values, and then another effect would be used to draw the scene again by darkening things that are behind others, which can be determined by querying a depth texture. So no, you can't do it with a single BasicEffect. Check out the MSDN article on shadow mapping. \$\endgroup\$ Commented Aug 13, 2014 at 18:41
  • \$\begingroup\$ Mh ok , so you mean, i have no choice, if i want implement shadow on my game , i need use HLSL shader ? \$\endgroup\$ Commented Aug 14, 2014 at 5:56
  • \$\begingroup\$ If your game is dynamic and you want shadows, then as far as I know yes. If your world is constant and nothing that casts a shadow changes, then you might be able to get away with pre-baked lighting and shadows. \$\endgroup\$ Commented Aug 14, 2014 at 6:35

1 Answer 1

3
\$\begingroup\$

No. BasicEffect cannot be told how to calculate the light-space coordinates, nor how to compare the depths. It is a "basic" Phong shader.

Implementing this is fairly straight-forward:
-Draw the scene from the light's perspective into a texture, recording the scene depth only.
-Draw the scene again from the camera's perspective into a different texture using a custom shader.

For each pixel, the lighting shader needs to:
-Project the world-space coordinate into both screen-space (drawing) and light-space (sampling)
-Convert the light-space coordinates into UV's and sample the depth texture to retrieve the distance from the light to the first object it struck
-Compare the sampled distance to the actual distance between the pixel's world coordinate and the light
-If the light-space distance is less than the camera-space distance, the pixel is in "shadow"; shadow could mean actually shadowed, "behind glass", etc. You can use this same technique any time you need to compare per-pixel visibility and not just for shadows; it's up to you.
-Calculate the color any way you'd like; fixed color, sampling, NDL
-Modify the "final" color by the shadow factor; pixels in shadow are dimmed or black.

Shadowed pixels usually have a much darker shade of their original color; all 3 components are reduced more or less evenly. For things like colored glass, you do slightly more specific math to reduce the intensity of individual channels; i.e. blue glass "cancels" a lot of the green and red, but doesn't necessarily modify the blue channel.

Edit:
I created this diagram for a question about colored glass and thought I'd include it here, too. Reference this diagram while stepping through the preceding algorithm. shadow diagram

Please refer to Reimer's or the MSDN article for further information. Reimer's has images.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .