/// <summary>
        /// Function to generate our 3D models for the scene.
        /// </summary>
        /// <remarks>
        /// <para>
        /// In this example we will be mixing 2D and 3D scene elements. So, of course, in 3D, we'll need something to render.  Since this is a space scene, we'll be rendering sphere(s). I've chosen to
        /// generate these models instead of loading them from disk because it's a pain to write a loader for those things, and I don't focus on 3D much in Gorgon. So, for now we'll use stock primitives.
        /// </para>
        /// </remarks>
        private void Generate3DModels()
        {
            // The 3D model for the earth. It has a diffuse/albedo map, a normal map and a specular map.
            var earthSphere = new IcoSphere(_graphics,
                                            3.0f,
                                            new DX.RectangleF(0, 0, 1, 1),
                                            DX.Vector3.Zero,
                                            3)
            {
                Rotation = new DX.Vector3(0, 45.0f, 0),                         // Start off with a 45 degree rotation on the Y axis so we can see our textures a little better on startup.
                Position = DX.Vector3.Zero,                                     // Set our translation to nothing for now, our "planet" type will handle positioning.
                Material =
                {
                    SpecularPower =               0.0f,
                    Albedo        = GorgonColor.Gray20,
                    PixelShader   = "PlanetPS",                                                 // The 3D model materials are quite simple.  They just reference their resources by name. We do live in the age of super duper
                    VertexShader  = "PlanetVS",                                                 // fast computers, so doing a few lookups is not going to kill our performance. This allows us to weakly reference the resources
                    Textures      =                                                             // which in turn keeps things nicely decoupled.
                    {
                        [0] = "earthmap1k",
                        [1] = "earthbump1k_NRM",
                        [2] = "earthspec1k"
                    }
                }
            };

            // This will serve as the cloud layer, it'll just sit on top of the other sphere to give the appearance of cloud cover moving over the land.
            // This will be additively blended with the land sphere above and use another pixel shader that has a slight emissive effect.
            var earthCloudSphere = new IcoSphere(_graphics,
                                                 3.01f,
                                                 new DX.RectangleF(0, 0, 1, 1),
                                                 DX.Vector3.Zero,
                                                 3)
            {
                Position = new DX.Vector3(0, 0, -0.2f),                         // Offset the clouds. If we render at the same place in Ortho camera mode, then it'll just overwrite, offsetting like this
                Material =                                                      // ensures that the clouds appear on top.
                {
                    SpecularPower =                         0,
                    Albedo        = GorgonColor.Gray20,
                    PixelShader   = "PlanetCloudPS",
                    VertexShader  = "PlanetVS",
                    BlendState    = GorgonBlendState.Additive,
                    Textures      =
                    {
                        [0] = "earthcloudmap"
                    }
                }
            };

            // Validate our references here so we don't have to wait too long to find out if I messed up.
            // Local functions are one of the best things added to C#. Delphi's had this for centuries.
            void Validate(Mesh mesh)
            {
                if (!_vertexShaders.ContainsKey(mesh.Material.VertexShader))
                {
                    throw new GorgonException(GorgonResult.CannotCreate, $"The vertex shader '{mesh.Material.VertexShader}' is missing.");
                }

                if (!_pixelShaders.ContainsKey(mesh.Material.PixelShader))
                {
                    throw new GorgonException(GorgonResult.CannotCreate, $"The pixel shader '{mesh.Material.PixelShader}' is missing.");
                }

                for (int i = 0; i < mesh.Material.Textures.Length; ++i)
                {
                    if (string.IsNullOrWhiteSpace(mesh.Material.Textures[i]))
                    {
                        continue;
                    }

                    if (!_textures.ContainsKey(mesh.Material.Textures[i]))
                    {
                        throw new GorgonException(GorgonResult.CannotCreate, $"The texture '{mesh.Material.Textures[i]}' is missing.");
                    }
                }
            }

            Validate(earthSphere);
            Validate(earthCloudSphere);

            _meshes[nameof(earthSphere)]      = earthSphere;
            _meshes[nameof(earthCloudSphere)] = earthCloudSphere;
        }
Esempio n. 2
0
        /// <summary>
        /// Function to build the meshes.
        /// </summary>
        private static void BuildMeshes()
        {
            var fnU = new DX.Vector3(0.5f, 1.0f, 0);
            var fnV = new DX.Vector3(1.0f, 1.0f, 0);

            DX.Vector3.Cross(ref fnU, ref fnV, out DX.Vector3 faceNormal);
            faceNormal.Normalize();

            _triangle = new Triangle(_graphics,
                                     new Vertex3D
            {
                Position = new DX.Vector4(-12.5f, -1.5f, 12.5f, 1),
                Normal   = faceNormal,
                UV       = new DX.Vector2(0, 1.0f)
            },
                                     new Vertex3D
            {
                Position = new DX.Vector4(0, 24.5f, 12.5f, 1),
                Normal   = faceNormal,
                UV       = new DX.Vector2(0.5f, 0.0f)
            },
                                     new Vertex3D
            {
                Position = new DX.Vector4(12.5f, -1.5f, 12.5f, 1),
                Normal   = faceNormal,
                UV       = new DX.Vector2(1.0f, 1.0f)
            })
            {
                Material =
                {
                    PixelShader  = "WaterShader",
                    VertexShader = "VertexShader",
                    Textures     =
                    {
                        [0] = "UV",
                        [1] = "Water_Normal",
                        [2] = "Water_Specular"
                    }
                },
                Position = new DX.Vector3(0, 0, 1.0f)
            };
            _renderer.Meshes.Add(_triangle);

            _plane = new Plane(_graphics, new DX.Vector2(25.0f, 25.0f), new RectangleF(0, 0, 1.0f, 1.0f), new DX.Vector3(90, 0, 0), 32, 32)
            {
                Position = new DX.Vector3(0, -1.5f, 1.0f),
                Material =
                {
                    PixelShader  = "WaterShader",
                    VertexShader = "VertexShader",
                    Textures     =
                    {
                        [0] = "UV",
                        [1] = "Water_Normal",
                        [2] = "Water_Specular"
                    }
                }
            };
            _renderer.Meshes.Add(_plane);

            _cube = new Cube(_graphics, new DX.Vector3(1, 1, 1), new RectangleF(0, 0, 1.0f, 1.0f), new DX.Vector3(45.0f, 0, 0))
            {
                Position = new DX.Vector3(0, 0, 1.5f),
                Material =
                {
                    SpecularPower =               0,
                    PixelShader   = "BumpMapShader",
                    VertexShader  = "VertexShader",
                    Textures      =
                    {
                        [0] = "UV",
                        [1] = "GorgonNormalMap"
                    }
                }
            };
            _renderer.Meshes.Add(_cube);

            _sphere = new Sphere(_graphics, 1.0f, new RectangleF(0.0f, 0.0f, 1.0f, 1.0f), DX.Vector3.Zero, 64, 64)
            {
                Position = new DX.Vector3(-2.0f, 1.0f, 0.75f),
                Material =
                {
                    PixelShader   = "PixelShader",
                    VertexShader  = "VertexShader",
                    SpecularPower =          0.75f,
                    Textures      =
                    {
                        [0] = "Earth"
                    }
                }
            };
            _renderer.Meshes.Add(_sphere);

            _icoSphere = new IcoSphere(_graphics, 5.0f, new DX.RectangleF(0, 0, 1, 1), DX.Vector3.Zero, 3)
            {
                Rotation = new DX.Vector3(0, -45.0f, 0),
                Position = new DX.Vector3(10, 2, 9.5f),
                Material =
                {
                    PixelShader  = "BumpMapShader",
                    VertexShader = "VertexShader",
                    Textures     =
                    {
                        [0] = "Earth",
                        [1] = "Earth_Normal",
                        [2] = "Earth_Specular"
                    }
                }
            };
            _renderer.Meshes.Add(_icoSphere);

            _clouds = new Sphere(_graphics, 5.125f, new RectangleF(0.0f, 0.0f, 1.0f, 1.0f), DX.Vector3.Zero, 16)
            {
                Position = new DX.Vector3(10, 2, 9.5f),
                Material =
                {
                    PixelShader  = "PixelShader",
                    VertexShader = "VertexShader",
                    BlendState   = GorgonBlendState.Additive,
                    Textures     =
                    {
                        [0] = "Clouds"
                    }
                }
            };
            _renderer.Meshes.Add(_clouds);
        }