Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: Monogame/XNA - 3D - nefunguje osvětlení a vlastní shadery u GraphicsDevice.DrawUserPrimitives<>()

V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Jiří Láska:11.11.2020 23:52

Ahoj,

Zde je celý kód:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace _3D_01
{
    public class Game1 : Game
    {
        private GraphicsDeviceManager graphics;
        private BasicEffect effect;

        private VertexPositionColor[] vertices; // the triangle

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            vertices = new VertexPositionColor[3];
            vertices[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color.Red);
            vertices[1] = new VertexPositionColor(new Vector3(10, 20, 0), Color.Green);
            vertices[2] = new VertexPositionColor(new Vector3(20, 0, 0), Color.Blue);

            base.Initialize();
        }

        protected override void LoadContent()
        {
            effect = new BasicEffect(GraphicsDevice);
            effect.VertexColorEnabled = true;
            effect.View = Matrix.CreateLookAt(new Vector3(0, 0, 40), new Vector3(0, 0, 0), new Vector3(0, 1, -1));
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(1.047f, GraphicsDevice.DisplayMode.AspectRatio, 1, 1000);
            effect.World = Matrix.CreateTranslation(new Vector3(0, 0, 0));
            //effect.EnableDefaultLighting();

            // LIGHT:
            effect.LightingEnabled = true;
            effect.DirectionalLight0.DiffuseColor = new Vector3(0.7f, 0.3f, 0.7f);
            effect.DirectionalLight0.SpecularColor = new Vector3(0.3f, 0.7f, 0.3f);
            effect.DirectionalLight0.Direction = new Vector3(0, 0.5f, -1);
            effect.DirectionalLight0.Enabled = true;

            effect.CurrentTechnique.Passes[0].Apply();
        }

        protected override void UnloadContent()
        {
        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, vertices, 0, 1); // drawing the triangle

            base.Draw(gameTime);
        }
    }
}

V kódu jsem vytvořil pole vertices se třemi vertexy, které tvoří trojúhelník. V metodě LoadContent() je nastavení shaderu BasicEffect. V metodě Draw() je vykreslení onoho trojúhelníku příkazem:

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, vertices, 0, 1); // drawing the triangle

Pokud v metodě LoadContent() zakomentuji tento kus kódu

//effect.EnableDefaultLighting();

// LIGHT:
effect.LightingEnabled = true;
effect.DirectionalLight0.DiffuseColor = new Vector3(0.7f, 0.3f, 0.7f);
effect.DirectionalLight0.SpecularColor = new Vector3(0.3f, 0.7f, 0.3f);
effect.DirectionalLight0.Direction = new Vector3(0, 0.5f, -1);
effect.DirectionalLight0.Enabled = true;

, tak vše funguje jak má (vykreslí se trojúhelník s červeným, zeleným a modrým vertexem). Pokud ale tento kus kódu, který nastavuje osvětlení v shaderu BasicEffect nechám nezakomentovaný, a/nebo se nechá nezakomentovaný příkaz effect.Enable­DefaultLightin­g();, tak se trojúhelník vykreslí černý. Nefunguje tedy osvětlení.

Zkrátka se mi zdá, že při použití příkazů pro nastavení osvětlení:

effect.EnableDefaultLighting();
// nebo
effect.LightingEnabled = true;

přestane správně fungovat příkaz pro vykreslení:

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, vertices, 0, 1); // drawing the triangle

a trojúhelník se vykreslí černě, světlo nefunguje.

Nevím, co dělám špatně.

Zkusil jsem: Zkoušel jsem dát nastavení BasicEffectu do metody Initialize() místo LoadContent().

Zkoušel jsem místo vykreslení trojúhelníku vykreslit model fbx. U toho osvětlení a nastavení osvětlení fungovalo. Nicméně na to se používají jiné příkazy:

private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
        {
            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();

                    effect.LightingEnabled = true; // Turn on the lighting subsystem.

                    effect.DirectionalLight0.DiffuseColor = new Vector3(1, 1, 1); // a reddish light
                    effect.DirectionalLight0.Direction = new Vector3(1, 1, -0.1f);  // coming along the x-axis
                    effect.DirectionalLight0.SpecularColor = new Vector3(0, 1, 0); // with green highlights

                    effect.AmbientLightColor = new Vector3(0.2f, 0.2f, 0.2f); // Add some overall ambient light.
                    effect.EmissiveColor = new Vector3(0.2f, 0.2f, 0.2f); // Sets some strange emmissive lighting.  This just looks weird.

                    effect.World = world;
                    effect.View = view;
                    effect.Projection = projection;
                }

                mesh.Draw();
            }
        }

V metodě Draw() se výše uvedená metoda zavolala:

DrawModel(model, world, view, projection);

Deklarace a definice parametrů vypadá takto:

private Model model;
private Matrix world = Matrix.CreateTranslation(new Vector3(0, 0, 0));
private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 50), new Vector3(0, 0, 0), Vector3.UnitY);
private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(60), 800f / 480f, 0.1f, 100f);

Pokud jsem do metody Draw() přidal opět vykreslení onoho trojúhelníku, opět se vykreslil černě, zatímco model se vykreslil správně.

Chci docílit: Důvod, proč nechci používat vykreslování modelu (ten způsob u kterého to funguje) je, že potřebuji za běhu hry měnit souřadnice vertexů modelu (potřebuji, aby se model hýbal, měnil tvar, a ne aby se pouze posouval a rotoval), proto ho chci mít sestavený přímo z vertexů a trojúhelníků, prostě mít pole vertexů a pole indexů definující trojúhelníky a díky tomu mít možnost měnit souřadnice vertexů. Následně vykreslit všechny trojúhelníky příkazem:

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, vertices, 0, 1); // drawing the triangle

, bohužel mi při tomto způsobu nefunguje osvětlení.

Nevím, co dělám špatně.

 
Odpovědět
11.11.2020 23:52
Avatar
Jiří Láska:11.11.2020 23:58

Ještě jsem zapomněl dodat, že ke stejnému problému dochází, když se snažím použít vlastní shader.

 
Nahoru Odpovědět
11.11.2020 23:58
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.