DynamicPrimitive lighting.

Dec 4, 2012 at 10:15 AM

Hello, I'm new in NineEngine. But I like it :)

Now my question. I'm trying to create model programmatically. I started with DynamicPrimitive. I added vertex gradually by AddVertex(Vector3, Color) method. All work's fine until draw. Geometry look's good, but there is no lighting. I suppose it's just because I didn't set normal vectors. But how to do that in DynamicPrimitives? Then I found LightingEnabled property in BasicMaterial. But DynamicPrimitive doesn't have Material property. Is there some way how to generate Model programmatically like DynamicPrimitive?

Here is link with screenshot of my app with no lighting (DynamicPrimitive is white).

http://www.dvorakmichal.eu/NoLighting.png

I really appreciate any help.

Thanks

Developer
Dec 4, 2012 at 10:50 AM

Take a look at how the primitives(plane) are built.

Eric

Dec 4, 2012 at 11:10 AM

Thanks for tip ;)

I'm going to check it out...

Dec 4, 2012 at 12:10 PM

ok, lighting is working now (see screenshot). But now I have really bad performance. Scene contains 169 my new custom primitives (inherited from Primitive<VertexPositionNormalTexture>). Scene contains 199848 vertices. Is it too much?

When I used base XNA method GraphicDevice.DrawUserIndexedPrimitives with vertex array and indexes there was no problem with FPS.
Even if I set CastShadow to false FPS isn't good :(

Thank you.

http://www.dvorakmichal.eu/CustomPrimitive.png

Coordinator
Dec 4, 2012 at 12:37 PM

Are you drawing the same amount of primitives when using DrawUserIndexedPrimitives?

Are there any performance improvements when turn off shadows? Have you tried to turn off shadowing for the main light?

What type of material are you using?

Because what Primitive does is basically calling into GraphicsDevice.DrawIndexedPrimtivies once you have setup your vertex data.

Dec 4, 2012 at 1:03 PM
  • Are you drawing the same amount of primitives when using DrawUserIndexedPrimitives?

Yes.

  • Are there any performance improvements when turn off shadows? Have you tried to turn off shadowing for the main light?

Yes, there are significant improvement. But FPS is still bad compared to DrawUserIndexedPrimitives.

  • What type of material are you using?

BasicMaterial.

  • Because what Primitive does is basically calling into GraphicsDevice.DrawIndexedPrimtivies once you have setup your vertex data.

I called DrawUserIndexedPrimitives this way:

m_GraphicDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, m_Vertices, 0, m_Vertices.Length, m_Indices, 0, m_Indices.Length / 3, VertexPositionColorNormal.VertexDeclaration);            

m_Vertices is array of VertexPositionColorNormal vertices. This array was generated in LoadContent method and doesn't change during game. 

The m_Indices is array of int. I used only BasicEffect with EnableDefaultLighting().

Coordinator
Dec 4, 2012 at 1:12 PM

What are the FPS for these 2 usages?

Dec 4, 2012 at 1:19 PM

DrawUserIndexedPrimitives: 60 FPS (XNA default limit)

Nine with DirectionalLight.CastShadow="False": 10 - 15 FPS

Nine with DirectionalLight.CastShadow="True": 3 - 5 FPS

Coordinator
Dec 5, 2012 at 3:41 AM

Hi michaldawn,

I tried to repro your scene but haven't been able to find much performance different between using Primitive and XNA DrawingUserPrimitives. The code I'm using look like;

namespace Test
{
    using System;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using Nine;
    using Nine.Components;
    using Nine.Graphics;
    using Nine.Graphics.Materials;
    using Nine.Graphics.Primitives;

    public class ReallyHugePrimitive : Primitive<VertexPositionNormal>
    {
        public ReallyHugePrimitive(GraphicsDevice graphicsDevice)
            : base(graphicsDevice) 
        {

        }

        protected override void OnBuild()
        {
            var random = new Random(1);
            for (int x = 0; x < 34; x++)
            {
                for (int z = 0; z < 34; z++)
                {
                    var position = new Vector3
                    {
                        X = x * 2 + (float)random.NextDouble() * 2,
                        Y = (float)random.NextDouble(),
                        Z = z * 2 + (float)random.NextDouble() * 2
                    };

                    AddVertex(position, new VertexPositionNormal
                    {
                        Position = position,
                        Normal = Vector3.Up,
                    });
                }
            }
        }
    }

    public class PrimitiveStressTest : ITestGame
    {
        public Scene CreateTestScene(GraphicsDevice graphics, ContentManager content)
        {
            var scene = new Scene();
            scene.Add(new Nine.Graphics.DirectionalLight(graphics) 
            {
                Direction = Vector3.Down,
                CastShadow = false,
            });

            for (int i = 0; i < 169; i++)
            {
                scene.Add(new ReallyHugePrimitive(graphics)
                {
                    CastShadow = false,
                    Material = new BasicMaterial(graphics) { LightingEnabled = true } 
                });
            }
            return scene;
        }
    }
}

You can copy this to the Test project in Engine Nine source code and see if it is slow. I'm getting 60+ FPS on my laptop, though these are just random vertices.

May be you can show me some of you code so that I can help diagnose it even further.

Thanks. 


Dec 5, 2012 at 6:16 AM

I really appreciate your help. I'm going to check it out today and let you know results.

Dec 5, 2012 at 9:56 AM

Your code runs good (60+ FPS). Now I'm going to find what I do wrong ;) I'll let you know.

Thx.

Dec 6, 2012 at 5:58 AM

Now my code works good. I used your example like template ;) The main difference between my old and new code  was in generating geometry (vertices). I didn't use OnBuild method, but my public AddVertex method in my "ReallyHugePrimitive" class. Then in Game.LoadContent() method i used this AddVertex method to add vertices to my "ReallyHugePrimitive" objects. 

Now in the new working version I put some data to "ReallyHugePrimitive" constructor and store them in private property. Then in OnBuild() method I use thid data to generate vertices.

Now works like a charm ;)
Thank you. I really appreciate your support.  

Dec 6, 2012 at 11:31 AM

Ok, just a additional question about shadows. Nine support only shadows from first Directional light and only for forward lighting. Right?

So when I want use SpotLight or PointLight I can't get shadows? For example land plane. Material group of plane contains DirectionalLightMaterialPart because shadows and DeferredLightsMaterialPart because PointLight... But only first of this two materials is aplied.

Is tehere some solution? Or what are your plans for the future of Nine engine and shadows?
Thank you.

Coordinator
Dec 6, 2012 at 12:16 PM
I think you can cast shadows from the first directional light for both deferred and forward lighting, as long as you put a ShadowMapMaterialPart to the material group.
Yes, SpotLight and PointLight can’t cast shadows at the moment and you cannot have more then 1 directional light shadows.
For future plans, I’ll implement multiple shadows of different light sources for deferred lighting first, since it’s a lot easier to manage.
For forward shadows, I think I can make SpotLight and PointLight cast shadows, but only 1 light at a time for a given scene. This is also true for lighting, you cannot have a point light and a spot light affecting the same object in forward lighting. Because I don’t want to get into the hell of multi-pass lighting.
So my suggestion is that if you are having more then 1 light sources, use deferred lighting, it’s a lot easier to manage.
Dec 6, 2012 at 12:40 PM
yufeih wrote:
I think you can cast shadows from the first directional light for both deferred and forward lighting, as long as you put a ShadowMapMaterialPart to the material group.

I'm not shure about that. Because (based on documentation) for shadows you must use DirectionalLightMaterialPart in material group. But for deferred lighting you must use DeferredLightsMaterialPart in material group. But when you use both, only one is aplied and you see only shadows (no spot or point lights) OR point light but no shadows.... I want see both (point light and shadows from directional light) on the ground.

If I'm doing something wrong, tell me please.

Thank you.

Coordinator
Dec 6, 2012 at 12:51 PM
No, for shadows, you must use the ShadowMapMaterialPart. You can combine ShadowMapMaterialPart with DeferredLightsMaterialPart.