Пример #1
0
        /// <summary>
        /// Sets the attribute ready for use in the VAO
        /// </summary>
        internal void SetAttribute(VertexLayout VertexLayout)
        {
            int offset = 0;

            if (VertexLayout.Position >= 0)
            {
                GL.VertexAttribPointer(VertexLayout.Position, 3, VertexAttribPointerType.Float, false, vertexSize, offset);
                offset += Vector3.SizeInBytes;
            }

            if (VertexLayout.Normal >= 0)
            {
                GL.VertexAttribPointer(VertexLayout.Normal, 3, VertexAttribPointerType.Float, false, vertexSize, offset);
                offset += Vector3.SizeInBytes;
            }

            if (VertexLayout.UV >= 0)
            {
                GL.VertexAttribPointer(VertexLayout.UV, 2, VertexAttribPointerType.Float, false, vertexSize, offset);
                offset += Vector2.SizeInBytes;                 //equivialant to API Vector2
            }

            if (VertexLayout.Color >= 0)
            {
                GL.VertexAttribPointer(VertexLayout.Color, 4, VertexAttribPointerType.Float, false, vertexSize, offset);
            }
        }
Пример #2
0
 /// <summary>
 /// Binds the VAO ready for drawing
 /// </summary>
 public void BindForDrawing(VertexLayout VertexLayout)
 {
     GL.BindVertexArray(handle);
     vbo.Bind();
     vbo.EnableAttribute(VertexLayout);
     vbo.SetAttribute(VertexLayout);
 }
Пример #3
0
 /// <summary>
 /// Draw using VAO
 /// </summary>
 /// <param name="VertexLayout"></param>
 /// <param name="DrawMode">Specifies the primitive or primitives that will be created from vertices</param>
 public void Draw(VertexLayout VertexLayout, PrimitiveType DrawMode)
 {
     vbo.Bind();
     vbo.EnableAttribute(VertexLayout);
     vbo.SetAttribute(VertexLayout);
     ibo.Draw(DrawMode);
     vbo.DisableAttribute(VertexLayout);
 }
Пример #4
0
 /// <summary>
 /// Draw using VAO
 /// </summary>
 /// <param name="VertexLayout"></param>
 /// <param name="DrawMode">Specifies the primitive or primitives that will be created from vertices</param>
 /// <param name="Start">Start position of vertex index</param>
 /// <param name="Count">Number of vertex indices to use</param>
 public void Draw(VertexLayout VertexLayout, PrimitiveType DrawMode, int Start, int Count)
 {
     vbo.Bind();
     vbo.EnableAttribute(VertexLayout);
     vbo.SetAttribute(VertexLayout);
     ibo.Draw(DrawMode, Start, Count);
     vbo.DisableAttribute(VertexLayout);
 }
Пример #5
0
        /// <summary>Enables a specific vertex attribute array</summary>
        internal void EnableAttribute(VertexLayout VertexLayout)
        {
            if (VertexLayout.Position >= 0)
            {
                GL.EnableVertexAttribArray(VertexLayout.Position);
            }

            if (VertexLayout.Normal >= 0)
            {
                GL.EnableVertexAttribArray(VertexLayout.Normal);
            }

            if (VertexLayout.UV >= 0)
            {
                GL.EnableVertexAttribArray(VertexLayout.UV);
            }

            if (VertexLayout.Color >= 0)
            {
                GL.EnableVertexAttribArray(VertexLayout.Color);
            }
        }
Пример #6
0
 /// <summary>
 /// Sets the VAO vertex layout attributes
 /// </summary>
 /// <remarks>
 /// These attributes remain valid unless a different shader is used to draw the object, and will be remembered by the VAO
 /// </remarks>
 public void SetAttributes(VertexLayout VertexLayout)
 {
     vbo.Bind();
     vbo.EnableAttribute(VertexLayout);
     vbo.SetAttribute(VertexLayout);
 }
Пример #7
0
        public static void CreateVAO(this StaticBackground background, VertexLayout vertexLayout)
        {
            float y0, y1;

            if (background.KeepAspectRatio)
            {
                int    tw = background.Texture.Width;
                int    th = background.Texture.Height;
                double hh = System.Math.PI * background.BackgroundImageDistance * th / (tw * background.Repetition);
                y0 = (float)(-0.5 * hh);
                y1 = (float)(1.5 * hh);
            }
            else
            {
                y0 = (float)(-0.125 * background.BackgroundImageDistance);
                y1 = (float)(0.375 * background.BackgroundImageDistance);
            }

            const int n = 32;

            Vector3f[]   bottom         = new Vector3f[n];
            Vector3f[]   top            = new Vector3f[n];
            double       angleValue     = 2.61799387799149 - 3.14159265358979 / n;
            const double angleIncrement = 6.28318530717958 / n;

            /*
             * To ensure that the whole background cylinder is rendered inside the viewing frustum,
             * the background is rendered before the scene with z-buffer writes disabled. Then,
             * the actual distance from the camera is irrelevant as long as it is inside the frustum.
             * */
            for (int i = 0; i < n; i++)
            {
                float x = (float)(background.BackgroundImageDistance * System.Math.Cos(angleValue));
                float z = (float)(background.BackgroundImageDistance * System.Math.Sin(angleValue));
                bottom[i]   = new Vector3f(x, y0, z);
                top[i]      = new Vector3f(x, y1, z);
                angleValue += angleIncrement;
            }

            float textureStart     = 0.5f * (float)background.Repetition / n;
            float textureIncrement = -(float)background.Repetition / n;
            float textureX         = textureStart;

            List <LibRenderVertex> vertexData = new List <LibRenderVertex>();
            List <ushort>          indexData  = new List <ushort>();

            for (int i = 0; i < n; i++)
            {
                int j           = (i + 1) % n;
                int indexOffset = vertexData.Count;

                // side wall
                vertexData.Add(new LibRenderVertex
                {
                    Position = top[i],
                    UV       = new Vector2f(textureX, 0.005f),
                    Color    = Color128.White
                });

                vertexData.Add(new LibRenderVertex
                {
                    Position = bottom[i],
                    UV       = new Vector2f(textureX, 0.995f),
                    Color    = Color128.White
                });

                vertexData.Add(new LibRenderVertex
                {
                    Position = bottom[j],
                    UV       = new Vector2f(textureX + textureIncrement, 0.995f),
                    Color    = Color128.White
                });

                vertexData.Add(new LibRenderVertex
                {
                    Position = top[j],
                    UV       = new Vector2f(textureX + textureIncrement, 0.005f),
                    Color    = Color128.White
                });

                indexData.AddRange(new[] { 0, 1, 2, 3 }.Select(x => x + indexOffset).Select(x => (ushort)x));

                // top cap
                vertexData.Add(new LibRenderVertex
                {
                    Position = new Vector3f(0.0f, top[i].Y, 0.0f),
                    UV       = new Vector2f(textureX + 0.5f * textureIncrement, 0.1f),
                    Color    = Color128.White
                });

                indexData.AddRange(new[] { 0, 3, 4 }.Select(x => x + indexOffset).Select(x => (ushort)x));

                // bottom cap
                vertexData.Add(new LibRenderVertex
                {
                    Position = new Vector3f(0.0f, bottom[i].Y, 0.0f),
                    UV       = new Vector2f(textureX + 0.5f * textureIncrement, 0.9f),
                    Color    = Color128.White
                });

                indexData.AddRange(new[] { 5, 2, 1 }.Select(x => x + indexOffset).Select(x => (ushort)x));

                // finish
                textureX += textureIncrement;
            }

            VertexArrayObject VAO = (VertexArrayObject)background.VAO;

            VAO?.UnBind();
            VAO?.Dispose();

            VAO = new VertexArrayObject();
            VAO.Bind();
            VAO.SetVBO(new VertexBufferObject(vertexData.ToArray(), BufferUsageHint.StaticDraw));
            VAO.SetIBO(new IndexBufferObjectU(indexData.ToArray(), BufferUsageHint.StaticDraw));
            VAO.SetAttributes(vertexLayout);
            VAO.UnBind();
            background.VAO = VAO;
        }
Пример #8
0
        /// <summary>Create an OpenGL/OpenTK VAO for a mesh</summary>
        /// <param name="isDynamic"></param>
        public static void CreateVAO(ref Mesh mesh, bool isDynamic, VertexLayout vertexLayout)
        {
            var hint = isDynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw;

            var vertexData = new List <LibRenderVertex>();
            var indexData  = new List <uint>();

            var normalsVertexData = new List <LibRenderVertex>();
            var normalsIndexData  = new List <uint>();

            for (int i = 0; i < mesh.Faces.Length; i++)
            {
                mesh.Faces[i].IboStartIndex        = indexData.Count;
                mesh.Faces[i].NormalsIboStartIndex = normalsIndexData.Count;

                foreach (var vertex in mesh.Faces[i].Vertices)
                {
                    var data = new LibRenderVertex
                    {
                        Position = mesh.Vertices[vertex.Index].Coordinates,
                        Normal   = vertex.Normal,
                        UV       = new Vector2f(mesh.Vertices[vertex.Index].TextureCoordinates)
                    };

                    var coloredVertex = mesh.Vertices[vertex.Index] as ColoredVertex;

                    if (coloredVertex != null)
                    {
                        data.Color = coloredVertex.Color;
                    }
                    else
                    {
                        data.Color = Color128.Transparent;
                    }

                    vertexData.Add(data);

                    var normalsData = new LibRenderVertex[2];
                    normalsData[0].Position = data.Position;
                    normalsData[1].Position = data.Position + data.Normal;

                    for (int j = 0; j < normalsData.Length; j++)
                    {
                        normalsData[j].Color = Color128.White;
                    }

                    normalsVertexData.AddRange(normalsData);
                }

                indexData.AddRange(Enumerable.Range(mesh.Faces[i].IboStartIndex, mesh.Faces[i].Vertices.Length).Select(x => (uint)x));
                normalsIndexData.AddRange(Enumerable.Range(mesh.Faces[i].NormalsIboStartIndex, mesh.Faces[i].Vertices.Length * 2).Select(x => (uint)x));
            }

            VertexArrayObject VAO = (VertexArrayObject)mesh.VAO;

            VAO?.UnBind();
            VAO?.Dispose();

            VAO = new VertexArrayObject();
            VAO.Bind();
            VAO.SetVBO(new VertexBufferObject(vertexData.ToArray(), hint));
            if (indexData.Count > 65530)
            {
                //Marginal headroom, although it probably doesn't matter
                VAO.SetIBO(new IndexBufferObjectI(indexData.ToArray(), hint));
            }
            else
            {
                VAO.SetIBO(new IndexBufferObjectU(indexData.Select(x => (ushort)x).ToArray(), hint));
            }

            VAO.SetAttributes(vertexLayout);
            VAO.UnBind();
            mesh.VAO = VAO;
            VertexArrayObject NormalsVAO = (VertexArrayObject)mesh.NormalsVAO;

            NormalsVAO?.UnBind();
            NormalsVAO?.Dispose();

            NormalsVAO = new VertexArrayObject();
            NormalsVAO.Bind();
            NormalsVAO.SetVBO(new VertexBufferObject(normalsVertexData.ToArray(), hint));
            if (normalsIndexData.Count > 65530)
            {
                //Marginal headroom, although it probably doesn't matter
                NormalsVAO.SetIBO(new IndexBufferObjectI(normalsIndexData.ToArray(), hint));
            }
            else
            {
                NormalsVAO.SetIBO(new IndexBufferObjectU(normalsIndexData.Select(x => (ushort)x).ToArray(), hint));
            }
            NormalsVAO.SetAttributes(vertexLayout);
            NormalsVAO.UnBind();
            mesh.NormalsVAO = NormalsVAO;
        }
Пример #9
0
        /// <summary>Create an OpenGL/OpenTK VAO for a mesh</summary>
        /// <param name="mesh">The mesh</param>
        /// <param name="isDynamic">Whether the mesh is dynamic (e.g. part of an animated object / train)</param>
        /// <param name="vertexLayout">The vertex layout to use</param>
        /// <param name="renderer">A reference to the base renderer</param>
        public static void CreateVAO(ref Mesh mesh, bool isDynamic, VertexLayout vertexLayout, BaseRenderer renderer)
        {
            try
            {
                var hint = isDynamic ? BufferUsageHint.DynamicDraw : BufferUsageHint.StaticDraw;

                var vertexData = new List <LibRenderVertex>();
                var indexData  = new List <uint>();

                var normalsVertexData = new List <LibRenderVertex>();
                var normalsIndexData  = new List <uint>();

                for (int i = 0; i < mesh.Faces.Length; i++)
                {
                    mesh.Faces[i].IboStartIndex        = indexData.Count;
                    mesh.Faces[i].NormalsIboStartIndex = normalsIndexData.Count;

                    foreach (var vertex in mesh.Faces[i].Vertices)
                    {
                        var data = new LibRenderVertex
                        {
                            Position = mesh.Vertices[vertex.Index].Coordinates,
                            Normal   = vertex.Normal,
                            UV       = new Vector2f(mesh.Vertices[vertex.Index].TextureCoordinates),
                            Color    = (mesh.Vertices[vertex.Index] as ColoredVertex)?.Color ?? Color128.White
                        };

                        vertexData.Add(data);

                        var normalsData = new LibRenderVertex[2];
                        normalsData[0].Position = data.Position;
                        normalsData[1].Position = data.Position + data.Normal;

                        for (int j = 0; j < normalsData.Length; j++)
                        {
                            normalsData[j].Color = Color128.White;
                        }

                        normalsVertexData.AddRange(normalsData);
                    }

                    indexData.AddRange(Enumerable.Range(mesh.Faces[i].IboStartIndex, mesh.Faces[i].Vertices.Length).Select(x => (uint)x));
                    normalsIndexData.AddRange(Enumerable.Range(mesh.Faces[i].NormalsIboStartIndex, mesh.Faces[i].Vertices.Length * 2).Select(x => (uint)x));
                }

                VertexArrayObject VAO = (VertexArrayObject)mesh.VAO;
                VAO?.UnBind();
                VAO?.Dispose();

                VAO = new VertexArrayObject();
                VAO.Bind();
                VAO.SetVBO(new VertexBufferObject(vertexData.ToArray(), hint));
                if (indexData.Count > 65530)
                {
                    //Marginal headroom, although it probably doesn't matter
                    VAO.SetIBO(new IndexBufferObjectUI(indexData.ToArray(), hint));
                }
                else
                {
                    VAO.SetIBO(new IndexBufferObjectUS(indexData.Select(x => (ushort)x).ToArray(), hint));
                }

                VAO.SetAttributes(vertexLayout);
                VAO.UnBind();
                mesh.VAO = VAO;
                VertexArrayObject NormalsVAO = (VertexArrayObject)mesh.NormalsVAO;
                NormalsVAO?.UnBind();
                NormalsVAO?.Dispose();

                NormalsVAO = new VertexArrayObject();
                NormalsVAO.Bind();
                NormalsVAO.SetVBO(new VertexBufferObject(normalsVertexData.ToArray(), hint));
                if (normalsIndexData.Count > 65530)
                {
                    //Marginal headroom, although it probably doesn't matter
                    NormalsVAO.SetIBO(new IndexBufferObjectUI(normalsIndexData.ToArray(), hint));
                }
                else
                {
                    NormalsVAO.SetIBO(new IndexBufferObjectUS(normalsIndexData.Select(x => (ushort)x).ToArray(), hint));
                }

                NormalsVAO.SetAttributes(vertexLayout);
                NormalsVAO.UnBind();
                mesh.NormalsVAO = NormalsVAO;
            }
            catch (Exception e)
            {
                renderer.ForceLegacyOpenGL = true;
                renderer.currentHost.AddMessage(MessageType.Error, false, $"Creating VAO failed with the following error: {e}");
            }
        }