예제 #1
0
        public override DrawGroup <Geometry> ApplyChanges()
        {
            if (!dataModified)
            {
                return(this);
            }

            int vertexCount = (int)count * TotalVertices;

            vertexPositionBuffer?.Dispose();
            vertexPositionBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexPosition), vertexCount, BufferUsage.WriteOnly);
            vertexPositionBuffer.SetData(vertexPositions, 0, vertexCount);

            transformBuffer?.Dispose();
            transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), vertexCount, BufferUsage.WriteOnly);
            transformBuffer.SetData(transforms, 0, vertexCount);

            colorBuffer?.Dispose();
            colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), vertexCount, BufferUsage.WriteOnly);
            colorBuffer.SetData(colors, 0, vertexCount);

            vertexBufferBindings = new VertexBufferBinding[]
            {
                new VertexBufferBinding(vertexPositionBuffer),
                new VertexBufferBinding(transformBuffer),
                new VertexBufferBinding(colorBuffer),
            };

            dataModified = false;

            return(this);
        }
예제 #2
0
        public void Dispose()
        {
            IsDisposed = true;

            vertexBuffer?.Dispose();
            indexBuffer?.Dispose();
        }
예제 #3
0
        private void InitTransforms(VertexBuffer modelVertices)
        {
            Array.Resize(ref instanceTransforms, Instances.Count);

            for (int i = 0; i < Instances.Count; i++)
            {
                instanceTransforms[i] = Instances[i];
            }

            if ((instanceVertexBuffer == null) || instanceTransforms.Length > instanceVertexBuffer.VertexCount)
            {
                instanceVertexBuffer?.Dispose();

                instanceVertexBuffer = new DynamicVertexBuffer(graphics,
                                                               InstanceVertexDeclaration,
                                                               instanceTransforms.Length,
                                                               BufferUsage.WriteOnly);
            }

            instanceVertexBuffer.SetData(
                instanceTransforms,
                0,
                instanceTransforms.Length,
                SetDataOptions.Discard);

            graphics.SetVertexBuffers(
                new VertexBufferBinding(modelVertices, 0, 0),
                new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                );
        }
예제 #4
0
        public override DrawGroup <Sprite> ApplyChanges()
        {
            if (!dataModified)
            {
                return(this);
            }

            int vertexCount = (int)count * 4;

            transformBuffer?.Dispose();
            transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), (int)count, BufferUsage.WriteOnly);
            transformBuffer.SetData(transforms, 0, (int)count);

            colorBuffer?.Dispose();
            colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), (int)count, BufferUsage.WriteOnly);
            colorBuffer.SetData(colors, 0, (int)count);

            textureCoordBuffer?.Dispose();
            textureCoordBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTexture), vertexCount, BufferUsage.WriteOnly);
            textureCoordBuffer.SetData(textureCoords, 0, vertexCount);

            vertexBufferBindings = new VertexBufferBinding[]
            {
                new VertexBufferBinding(sharedGeometry.VertexPositionBuffer),
                new VertexBufferBinding(transformBuffer, 0, 1),
                new VertexBufferBinding(colorBuffer, 0, 1),
                new VertexBufferBinding(textureCoordBuffer)
            };

            dataModified = false;

            return(this);
        }
예제 #5
0
        public static void SetVertices <T>(GraphicsDevice device, ref DynamicVertexBuffer buffer, VertexDeclaration declaration, T[] data) where T : struct
        {
            // If we have more instances than room in our vertex buffer, grow it to the necessary size.
            if (buffer == null || data.Length > buffer.VertexCount)
            {
                buffer?.Dispose();

                buffer = new DynamicVertexBuffer(device, declaration, data.Length, BufferUsage.WriteOnly);
            }

            // Transfer the latest instance transform matrices into the instanceVertexBuffer.
            buffer.SetData(data, 0, data.Length, SetDataOptions.Discard);
        }
예제 #6
0
        private void UpdateBuffer()
        {
            transformBuffer?.Dispose();

            transformBuffer = new DynamicVertexBuffer(Engine.Graphics.GraphicsDevice, typeof(VertexTransformColor), transforms.Length, BufferUsage.WriteOnly);
            transformBuffer.SetData(transforms);

            vertexBufferBindings = new VertexBufferBinding[]
            {
                new VertexBufferBinding(sharedShapeData.Geometry),
                new VertexBufferBinding(transformBuffer, 0, 1)
            };
        }
예제 #7
0
        private void EnsureBufferSize(int vbs, int ibs)
        {
            if (_vertexBuffer == null || _vertexBuffer.VertexCount < vbs)
            {
                _vertexBuffer?.Dispose();
                _vertexBuffer = new DynamicVertexBuffer(GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, vbs, BufferUsage.WriteOnly);
            }

            if (_indexBuffer == null || _indexBuffer.IndexCount < ibs)
            {
                _indexBuffer?.Dispose();
                _indexBuffer = new DynamicIndexBuffer(GraphicsDevice, IndexElementSize.ThirtyTwoBits, ibs, BufferUsage.WriteOnly);
            }
        }
예제 #8
0
        public void Remove()
        {
            if (!lightSourceParams.Persistent)
            {
                LightSprite?.Remove();
                OverrideLightTexture?.Remove();
            }

            DeformableLightSprite?.Remove();
            DeformableLightSprite = null;

            lightVolumeBuffer?.Dispose();
            lightVolumeBuffer = null;

            lightVolumeIndexBuffer?.Dispose();
            lightVolumeIndexBuffer = null;

            GameMain.LightManager.RemoveLight(this);
        }
예제 #9
0
        /// <summary>
        /// Updates the vertex-buffer with the newest information
        /// </summary>
        public void Update()
        {
            GameObject[] safe = GameObjects.ToArray();

            // Store the size
            VertexBufferSize = safe.Length;

            // Vertex-buffer with 0 elements fails => handle this by explicitly doing nothing.
            // Important: Now there is most likely an instance remaining in the buffer => handle this case in the draw
            if (safe.Length == 0)
            {
                return;
            }

            // Update the size (which is only done if needed) and transfer all needed values for the vertex-description
            Array.Resize(ref VertexInformation, VertexBufferSize);

            for (int i = 0; i < VertexBufferSize; ++i)
            {
                if (safe[i] == null)
                {
                    continue;
                }

                VertexInformation[i].Matrix = safe[i].transform.World;
                VertexInformation[i].Alpha  = safe[i].Alpha;
            }

            // Re-Initialize the vertex-buffer if needed
            if (VertexBuffer == null || VertexBufferSize > VertexBuffer.VertexCount)
            {
                VertexBuffer?.Dispose();

                VertexBuffer = new DynamicVertexBuffer(Graphics.gD, VertexPositionAlpha.InstanceVertexDeclaration,
                                                       VertexBufferSize, BufferUsage.WriteOnly);
            }

            // Transfer the latest instance gameObject matrices into the vertex-buffer.
            VertexBuffer.SetData(VertexInformation, 0, VertexInformation.Length, SetDataOptions.Discard);
        }
예제 #10
0
        private void CreateVertexBufferBindings()
        {
            if (Entities.Count <= 0)
            {
                return;
            }

            transformBuffer?.Dispose();
            transformBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexTransform), transformData.Length, BufferUsage.WriteOnly);
            transformBuffer.SetData(transformData);

            colorBuffer?.Dispose();
            colorBuffer = new DynamicVertexBuffer(graphicsDevice, typeof(VertexColor), colorData.Length, BufferUsage.WriteOnly);
            colorBuffer.SetData(colorData);

            vertexBufferBindings = new VertexBufferBinding[]
            {
                new VertexBufferBinding(geometry.VertexPositionBuffer),
                new VertexBufferBinding(transformBuffer, 0, 1),
                new VertexBufferBinding(colorBuffer, 0, 1)
            };
        }
예제 #11
0
        internal void GetInstanceBuffer(ref Vector3 cameraPosition, bool forceUpdate, out VertexBuffer vertexBuffer, out int vertexCount)
        {
            if (instanceTransforms == null || instanceTransforms.Length <= 0)
            {
                vertexBuffer = null;
                vertexCount  = 0;
                return;
            }

            instanceTransformsNeedsUpdate |= forceUpdate;
            if (instanceBuffer == null || instanceTransformsNeedsUpdate || instanceBuffer.VertexCount < instanceTransforms.Length)
            {
                if (vertexDeclaration == null)
                {
                    vertexDeclaration = new VertexDeclaration
                                        (
                        new VertexElement(0, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 4),
                        new VertexElement(16, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 5),
                        new VertexElement(32, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 6),
                        new VertexElement(48, VertexElementFormat.Vector4, VertexElementUsage.BlendWeight, 7)
                                        );
                }

                if (instanceBuffer != null)
                {
                    instanceBuffer.Dispose();
                }

                instanceBuffer = new DynamicVertexBuffer(GraphicsDevice, vertexDeclaration, instanceTransforms.Length, BufferUsage.WriteOnly);
                instanceTransformsNeedsUpdate = true;
            }

            vertexCount  = instanceCount;
            vertexBuffer = instanceBuffer;

            if (instanceTransformsNeedsUpdate || instanceBuffer.IsContentLost)
            {
                instanceTransformsNeedsUpdate = false;

                var data = instanceTransforms;
                instanceCount = vertexCount = instanceTransforms.Length;

                if (ViewDistance.HasValue)
                {
                    Matrix worldToLocal = AbsoluteTransform;
                    Matrix.Invert(ref worldToLocal, out worldToLocal);
                    Vector3.Transform(ref cameraPosition, ref worldToLocal, out cameraPosition);

                    PopulateVisibleInstances(ref cameraPosition);

                    data          = VisibleInstanceTransforms;
                    instanceCount = vertexCount = VisibleInstanceCount;
                    if (instanceCount <= 0)
                    {
                        return;
                    }
                }

                instanceBuffer.SetData(data, 0, instanceCount, SetDataOptions.Discard);
            }
        }
        private static void DrawInstancedTowers(int playerNum, int towerType, int amount)
        {
            //int amount = units[playerNum][unitType].Count;

            if (amount == 0)
                return;

            instanceVertexBuffer = null; ///////////////////////////////////////////////////////////////////FIX THIS!
            // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
            if ((instanceVertexBuffer == null) ||
                (amount > instanceVertexBuffer.VertexCount))
            {
                if (instanceVertexBuffer != null)
                    instanceVertexBuffer.Dispose();

                instanceVertexBuffer = new DynamicVertexBuffer(ScreenManager.Game.GraphicsDevice, instanceVertexDeclaration,
                                                               amount, BufferUsage.WriteOnly);
            }

            // Transfer the latest instance transform matrices into the instanceVertexBuffer.
            instanceVertexBuffer.SetData(towerTransforms, 0, amount, SetDataOptions.Discard);

            for (int i = 0; i < instancedModels[towerType][playerNum].Meshes.Count; i++)
            {
                for (int j = 0; j < instancedModels[towerType][playerNum].Meshes[i].MeshParts.Count; j++)
                {

                    // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
                    ScreenManager.Game.GraphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].VertexBuffer,
                            instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].VertexOffset, 0),
                        new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                    );

                    ScreenManager.Game.GraphicsDevice.Indices = instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].IndexBuffer;

                    // Set up the instance rendering effect.
                    Effect effect = instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].Effect;

                    effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];

                    effect.Parameters["World"].SetValue(instancedModelBones[towerType][playerNum][instancedModels[towerType][playerNum].Meshes[i].ParentBone.Index]);
                    effect.Parameters["View"].SetValue(cameraManager.ViewMatrix);
                    effect.Parameters["Projection"].SetValue(cameraManager.ProjectionMatrix);

                    // Draw all the instance copies in a single call.
                    for (int k = 0; k < effect.CurrentTechnique.Passes.Count; k++)
                    {
                        effect.CurrentTechnique.Passes[k].Apply();

                        ScreenManager.Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                                instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].NumVertices,
                                                                instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].StartIndex,
                                                                instancedModels[towerType][playerNum].Meshes[i].MeshParts[j].PrimitiveCount,
                                                                amount);
                    }
                }
            }
        }
예제 #13
0
        private void DrawBatch(DrawingContext context, ref PrimitiveGroupEntry entry, Material material)
        {
            if (entry.VertexCount <= 0 && entry.IndexCount <= 0)
            {
                return;
            }

            material.texture = entry.Texture;
            material.world   = entry.World.HasValue ? entry.World.Value * AbsoluteTransform : AbsoluteTransform;
            material.BeginApply(context);

#if !WINDOWS_PHONE
            if (entry.LineWidth > 0)
            {
                if (thickLineMaterial == null)
                {
                    thickLineMaterial = new ThickLineMaterial(graphics);
                }
                thickLineMaterial.Thickness = entry.LineWidth;
                thickLineMaterial.world     = material.world;
                thickLineMaterial.BeginApply(context);
            }
#endif

            var vertexBufferSize = vertexSegments[entry.Segment + 1] - vertexSegments[entry.Segment];
#if SILVERLIGHT
            if (vertexBuffer == null || vertexBuffer.VertexCount < vertexBufferSize)
#else
            if (vertexBuffer == null || vertexBuffer.VertexCount < vertexBufferSize || vertexBuffer.IsContentLost)
#endif
            {
                if (vertexBuffer != null)
                {
                    vertexBuffer.Dispose();
                }
                vertexBuffer = new DynamicVertexBuffer(graphics, typeof(VertexPositionColorNormalTexture), Math.Max(initialBufferCapacity, vertexBufferSize), BufferUsage.WriteOnly);
            }

            context.SetVertexBuffer(null, 0);
            vertexBuffer.SetData(vertexData, vertexSegments[entry.Segment], vertexBufferSize, SetDataOptions.Discard);

            // Previous segments are not used, so use SetDataOption.Discard to boost performance.
            context.SetVertexBuffer(vertexBuffer, 0);

            if (entry.IndexCount > 0)
            {
                var indexBufferSize = indexSegments[entry.Segment + 1] - indexSegments[entry.Segment];
#if SILVERLIGHT
                if (indexBuffer == null || indexBuffer.IndexCount < indexBufferSize)
#else
                if (indexBuffer == null || indexBuffer.IndexCount < indexBufferSize || indexBuffer.IsContentLost)
#endif
                {
                    if (indexBuffer != null)
                    {
                        indexBuffer.Dispose();
                    }
                    indexBuffer = new DynamicIndexBuffer(graphics, IndexElementSize.SixteenBits, Math.Max(initialBufferCapacity, indexBufferSize), BufferUsage.WriteOnly);
                }

                graphics.Indices = null;
                indexBuffer.SetData(indexData, indexSegments[entry.Segment], indexBufferSize, SetDataOptions.Discard);

                var primitiveCount = Helper.GetPrimitiveCount(entry.PrimitiveType, entry.IndexCount);
                graphics.Indices = indexBuffer;
                graphics.DrawIndexedPrimitives(entry.PrimitiveType, 0, entry.StartVertex, entry.VertexCount, entry.StartIndex, primitiveCount);
            }
            else
            {
                var primitiveCount = Helper.GetPrimitiveCount(entry.PrimitiveType, entry.VertexCount);
                graphics.DrawPrimitives(entry.PrimitiveType, entry.StartVertex, primitiveCount);
            }

            material.EndApply(context);
        }
예제 #14
0
        private void CalculateLightVertices(List <Vector2> rayCastHits)
        {
            List <VertexPositionColorTexture> vertices = new List <VertexPositionColorTexture>();

            Vector2 drawPos = position;

            if (ParentSub != null)
            {
                drawPos += ParentSub.DrawPosition;
            }

            float cosAngle = (float)Math.Cos(Rotation);
            float sinAngle = -(float)Math.Sin(Rotation);

            Vector2 uvOffset            = Vector2.Zero;
            Vector2 overrideTextureDims = Vector2.One;

            if (overrideLightTexture != null)
            {
                overrideTextureDims = new Vector2(overrideLightTexture.SourceRect.Width, overrideLightTexture.SourceRect.Height);
                uvOffset            = (overrideLightTexture.Origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
            }

            // Add a vertex for the center of the mesh
            vertices.Add(new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
                                                        Color.White, new Vector2(0.5f, 0.5f) + uvOffset));

            // Add all the other encounter points as vertices
            // storing their world position as UV coordinates
            for (int i = 0; i < rayCastHits.Count; i++)
            {
                Vector2 vertex = rayCastHits[i];

                //we'll use the previous and next vertices to calculate the normals
                //of the two segments this vertex belongs to
                //so we can add new vertices based on these normals
                Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1];
                Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0];

                Vector2 rawDiff = vertex - drawPos;
                Vector2 diff    = rawDiff;
                diff /= range * 2.0f;
                if (overrideLightTexture != null)
                {
                    //calculate texture coordinates based on the light's rotation
                    Vector2 originDiff = diff;

                    diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle;
                    diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle;
                    diff  *= (overrideTextureDims / overrideLightTexture.size) * 2.0f;

                    diff += uvOffset;
                }

                //calculate normal of first segment
                Vector2 nDiff1 = vertex - nextVertex;
                float   tx     = nDiff1.X; nDiff1.X = -nDiff1.Y; nDiff1.Y = tx;
                nDiff1 /= Math.Max(Math.Abs(nDiff1.X), Math.Abs(nDiff1.Y));
                //if the normal is pointing towards the light origin
                //rather than away from it, invert it
                if (Vector2.DistanceSquared(nDiff1, rawDiff) > Vector2.DistanceSquared(-nDiff1, rawDiff))
                {
                    nDiff1 = -nDiff1;
                }

                //calculate normal of second segment
                Vector2 nDiff2 = prevVertex - vertex;
                tx      = nDiff2.X; nDiff2.X = -nDiff2.Y; nDiff2.Y = tx;
                nDiff2 /= Math.Max(Math.Abs(nDiff2.X), Math.Abs(nDiff2.Y));
                //if the normal is pointing towards the light origin
                //rather than away from it, invert it
                if (Vector2.DistanceSquared(nDiff2, rawDiff) > Vector2.DistanceSquared(-nDiff2, rawDiff))
                {
                    nDiff2 = -nDiff2;
                }

                //add the normals together and use some magic numbers to create
                //a somewhat useful/good-looking blur
                Vector2 nDiff = nDiff1 + nDiff2;
                nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y));
                nDiff *= 50.0f;

                //finally, create the vertices
                VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
                                                                                     Color.White, new Vector2(0.5f, 0.5f) + diff);
                VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
                                                                                     Color.White * 0.0f, new Vector2(0.5f, 0.5f) + diff);

                vertices.Add(fullVert);
                vertices.Add(fadeVert);
            }

            // Compute the indices to form triangles
            List <short> indices = new List <short>();

            for (int i = 0; i < rayCastHits.Count - 1; i++)
            {
                //main light body
                indices.Add(0);
                indices.Add((short)((i * 2 + 3) % vertices.Count));
                indices.Add((short)((i * 2 + 1) % vertices.Count));

                //faded light
                indices.Add((short)((i * 2 + 1) % vertices.Count));
                indices.Add((short)((i * 2 + 3) % vertices.Count));
                indices.Add((short)((i * 2 + 4) % vertices.Count));

                indices.Add((short)((i * 2 + 2) % vertices.Count));
                indices.Add((short)((i * 2 + 1) % vertices.Count));
                indices.Add((short)((i * 2 + 4) % vertices.Count));
            }

            //main light body
            indices.Add(0);
            indices.Add((short)(1));
            indices.Add((short)(vertices.Count - 2));

            //faded light
            indices.Add((short)(1));
            indices.Add((short)(vertices.Count - 1));
            indices.Add((short)(vertices.Count - 2));

            indices.Add((short)(1));
            indices.Add((short)(2));
            indices.Add((short)(vertices.Count - 1));

            vertexCount = vertices.Count;
            indexCount  = indices.Count;

            //TODO: a better way to determine the size of the vertex buffer and handle changes in size?
            //now we just create a buffer for 64 verts and make it larger if needed
            if (lightVolumeBuffer == null)
            {
                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None);
            }
            else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
            {
                lightVolumeBuffer.Dispose();
                lightVolumeIndexBuffer.Dispose();

                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
            }

            lightVolumeBuffer.SetData <VertexPositionColorTexture>(vertices.ToArray());
            lightVolumeIndexBuffer.SetData <short>(indices.ToArray());
        }
예제 #15
0
        public virtual void Draw(GameTime gameTime, Effect thisEffect)
        {
            if (instanceTransformMatrices.Count == 0)
            {
                return;
            }

            // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
            if ((instanceVertexBuffer == null) ||
                (instanceTransformMatrices.Count > instanceVertexBuffer.VertexCount))
            {
                if (instanceVertexBuffer != null)
                {
                    instanceVertexBuffer.Dispose();
                }

                instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, instanceVertexDeclaration, instanceTransformMatrices.Count, BufferUsage.WriteOnly);
            }

            // Transfer the latest instance transform matrices into the instanceVertexBuffer.
            instanceVertexBuffer.SetData(instanceTransformMatrices.Values.ToArray(), 0, instanceTransformMatrices.Count, SetDataOptions.Discard);

            bones = animationPlayer.GetSkinTransforms();
            if (thisEffect.Parameters["Bones"] != null)
            {
                thisEffect.Parameters["Bones"].SetValue(bones);
            }

            for (int m = 0; m < thisMesh.Meshes.Count; m++)
            {
                int pcnt = 0;
                for (int mp = 0; mp < thisMesh.Meshes[m].MeshParts.Count; mp++)
                {
                    if (thisEffect.CurrentTechnique.Name == "ShadowMapH") // Shadow Map
                    {
                    }
                    else
                    {
                        thisEffect.CurrentTechnique = thisEffect.Techniques["BasicTextureH"];
                        if (thisEffect.Parameters["vp"] != null)
                        {
                            thisEffect.Parameters["vp"].SetValue(Camera.View * Camera.Projection);
                        }

                        if (thisEffect.Parameters["v"] != null)
                        {
                            thisEffect.Parameters["v"].SetValue(Camera.View);
                        }

                        if (thisEffect.Parameters["p"] != null)
                        {
                            thisEffect.Parameters["p"].SetValue(Camera.Projection);
                        }

                        thisEffect.Parameters["color"].SetValue(Color.White.ToVector3());

                        // Texture
                        if (TextureMaterials.Count > 0 && pcnt < TextureMaterials.Count)
                        {
                            thisEffect.Parameters["textureMat"].SetValue(AssetManager.GetAsset <Texture2D>(TextureMaterials[pcnt]));
                        }
                        else
                        {
                            if (((SkinnedEffect)thisMesh.Meshes[m].MeshParts[mp].Effect).Texture != null)
                            {
                                thisEffect.Parameters["textureMat"].SetValue(((SkinnedEffect)thisMesh.Meshes[m].MeshParts[mp].Effect).Texture);
                            }
                            else
                            {
                                thisEffect.Parameters["textureMat"].SetValue(blank);
                            }
                        }

                        // Normals
                        if (NormalMaterials.Count > 0 && pcnt < NormalMaterials.Count)
                        {
                            thisEffect.Parameters["BumpMap"].SetValue(AssetManager.GetAsset <Texture2D>(NormalMaterials[pcnt]));
                        }
                        else
                        {
                            thisEffect.Parameters["BumpMap"].SetValue(blank);
                        }

                        // Specula
                        if (SpeculaMaterials.Count > 0 && pcnt < SpeculaMaterials.Count)
                        {
                            thisEffect.Parameters["specularMap"].SetValue(AssetManager.GetAsset <Texture2D>(SpeculaMaterials[pcnt]));
                        }
                        else
                        {
                            thisEffect.Parameters["specularMap"].SetValue(blank);
                        }

                        // Glow
                        if (GlowMaterials.Count > 0 && pcnt < GlowMaterials.Count)
                        {
                            thisEffect.Parameters["glowMap"].SetValue(AssetManager.GetAsset <Texture2D>(GlowMaterials[pcnt]));
                        }
                        else
                        {
                            thisEffect.Parameters["glowMap"].SetValue(blank);
                        }

                        // Reflection
                        if (ReflectionMaterials.Count > 0 && pcnt < ReflectionMaterials.Count)
                        {
                            thisEffect.Parameters["reflectionMap"].SetValue(AssetManager.GetAsset <Texture2D>(ReflectionMaterials[pcnt]));
                        }
                        else
                        {
                            thisEffect.Parameters["reflectionMap"].SetValue(blank);
                        }

                        pcnt++;
                    }

                    thisEffect.CurrentTechnique.Passes[0].Apply();

                    GraphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(partVertexBuffer[mp], 0, 0),
                        new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                        );

                    GraphicsDevice.Indices = indexBuffer;
                    Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                                partVertexBuffer[mp].VertexCount, 0,
                                                                partVertexBuffer[mp].VertexCount / 3,
                                                                instanceTransformMatrices.Count);
                }
            }

            if (RenderBounds)
            {
                DrawBounds();
            }
        }
예제 #16
0
        private void DrawInstances()
        {
            if (instances.Count == 0)
            {
                return;
            }
            numPolygons = 0;

            // Gather instance transform matrices into a single array.
            Array.Resize(ref instanceVertices, instances.Count);

            for (int i = 0; i < instances.Count; i++)
            {
                instanceVertices[i].Transform = instances[i].Transform;
                instanceVertices[i].Size      = instances[i].Size;
                instanceVertices[i].Color     = instances[i].Color;
            }

            // Draw all instances using hardware instancing
            // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
            if ((instanceVertexBuffer == null) ||
                (instanceVertices.Length > instanceVertexBuffer.VertexCount))
            {
                if (instanceVertexBuffer != null)
                {
                    instanceVertexBuffer.Dispose();
                }

                instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, typeof(TowerInstanceVertex),
                                                               instanceVertices.Length, BufferUsage.WriteOnly);
            }

            // Transfer the latest instance transform matrices into the instanceVertexBuffer.
            instanceVertexBuffer.SetData(instanceVertices, 0, instanceVertices.Length, SetDataOptions.Discard);

            foreach (ModelMesh mesh in model.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
                    GraphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                        new VertexBufferBinding(instanceVertexBuffer, 0, 1)
                        );

                    GraphicsDevice.Indices = meshPart.IndexBuffer;

                    // Set up the instance rendering effect.
                    Effect effect = meshPart.Effect;

                    effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];

                    effect.Parameters["World"].SetValue(Matrix.Identity);
                    effect.Parameters["View"].SetValue(camera.View);
                    effect.Parameters["Projection"].SetValue(camera.Projection);
                    effect.Parameters["NormalMap"].SetValue(normalMap);
                    effect.Parameters["DiffuseMap"].SetValue(diffuseMap);

                    // Draw all the instance copies in a single call.
                    foreach (EffectPass pass in effect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                               meshPart.NumVertices, meshPart.StartIndex,
                                                               meshPart.PrimitiveCount, instanceVertices.Length);
                    }

                    numPolygons += meshPart.PrimitiveCount * instanceVertices.Length;
                }
            }
        }
예제 #17
0
    static unsafe void RunCompute(Sample sample, bool indirectSupported)
    {
        // build vertex layouts
        var quadLayout = new VertexLayout();

        quadLayout.Begin()
        .Add(VertexAttributeUsage.Position, 2, VertexAttributeType.Float)
        .End();

        var computeLayout = new VertexLayout();

        computeLayout.Begin()
        .Add(VertexAttributeUsage.TexCoord0, 4, VertexAttributeType.Float)
        .End();

        // static quad data
        var vb = new VertexBuffer(MemoryBlock.FromArray(QuadVertices), quadLayout);
        var ib = new IndexBuffer(MemoryBlock.FromArray(QuadIndices));

        // create compute buffers
        var currPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite);
        var currPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite);
        var prevPositionBuffer0 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite);
        var prevPositionBuffer1 = new DynamicVertexBuffer(1 << 15, computeLayout, BufferFlags.ComputeReadWrite);

        // load shaders
        var particleProgram        = ResourceLoader.LoadProgram("vs_particle", "fs_particle");
        var initInstancesProgram   = ResourceLoader.LoadProgram("cs_init_instances");
        var updateInstancesProgram = ResourceLoader.LoadProgram("cs_update_instances");

        // indirect rendering support
        var  indirectProgram = SharpBgfx.Program.Invalid;
        var  indirectBuffer  = IndirectBuffer.Invalid;
        bool useIndirect     = false;

        if (indirectSupported)
        {
            indirectProgram = ResourceLoader.LoadProgram("cs_indirect");
            indirectBuffer  = new IndirectBuffer(2);
            useIndirect     = true;
        }

        // setup params uniforms
        var paramData = new ParamsData {
            TimeStep          = 0.0157f,
            DispatchSize      = 32,
            Gravity           = 0.109f,
            Damping           = 0.25f,
            ParticleIntensity = 0.64f,
            ParticleSize      = 0.279f,
            BaseSeed          = 57,
            ParticlePower     = 3.5f,
            InitialSpeed      = 3.2f,
            InitialShape      = 1,
            MaxAccel          = 100.0f
        };

        // have the compute shader run initialization
        var u_params = new Uniform("u_params", UniformType.Vector4, 3);

        Bgfx.SetUniform(u_params, &paramData, 3);
        Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Write);
        Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Write);
        Bgfx.Dispatch(0, initInstancesProgram, MaxParticleCount / ThreadGroupUpdateSize);

        // start the frame clock
        var clock = new Clock();

        clock.Start();

        // main loop
        while (sample.ProcessEvents(ResetFlags.Vsync))
        {
            // tick the clock
            var elapsed = clock.Frame();
            var time    = clock.TotalTime();

            // write some debug text
            Bgfx.DebugTextClear();
            Bgfx.DebugTextWrite(0, 1, DebugColor.White, DebugColor.Blue, "SharpBgfx/Samples/24-NBody");
            Bgfx.DebugTextWrite(0, 2, DebugColor.White, DebugColor.Cyan, "Description: N-body simulation with compute shaders using buffers.");
            Bgfx.DebugTextWrite(0, 3, DebugColor.White, DebugColor.Cyan, "Frame: {0:F3} ms", elapsed * 1000);

            // fill the indirect buffer if we're using it
            if (useIndirect)
            {
                Bgfx.SetUniform(u_params, &paramData, 3);
                Bgfx.SetComputeBuffer(0, indirectBuffer, ComputeBufferAccess.Write);
                Bgfx.Dispatch(0, indirectProgram);
            }

            // update particle positions
            Bgfx.SetComputeBuffer(0, prevPositionBuffer0, ComputeBufferAccess.Read);
            Bgfx.SetComputeBuffer(1, currPositionBuffer0, ComputeBufferAccess.Read);
            Bgfx.SetComputeBuffer(2, prevPositionBuffer1, ComputeBufferAccess.Write);
            Bgfx.SetComputeBuffer(3, currPositionBuffer1, ComputeBufferAccess.Write);
            Bgfx.SetUniform(u_params, &paramData, 3);
            if (useIndirect)
            {
                Bgfx.Dispatch(0, updateInstancesProgram, indirectBuffer, 1);
            }
            else
            {
                Bgfx.Dispatch(0, updateInstancesProgram, paramData.DispatchSize);
            }

            // ping-pong the buffers for next frame
            Swap(ref currPositionBuffer0, ref currPositionBuffer1);
            Swap(ref prevPositionBuffer0, ref prevPositionBuffer1);

            // view transforms for particle rendering
            var viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0.0f, 0.0f, -45.0f), -Vector3.UnitZ, Vector3.UnitY);
            var projMatrix = Matrix4x4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)sample.WindowWidth / sample.WindowHeight, 0.1f, 10000.0f);
            Bgfx.SetViewTransform(0, &viewMatrix.M11, &projMatrix.M11);
            Bgfx.SetViewRect(0, 0, 0, sample.WindowWidth, sample.WindowHeight);

            // draw the particles
            Bgfx.SetVertexBuffer(vb);
            Bgfx.SetIndexBuffer(ib);
            Bgfx.SetInstanceDataBuffer(currPositionBuffer0, 0, paramData.DispatchSize * ThreadGroupUpdateSize);
            Bgfx.SetRenderState(RenderState.ColorWrite | RenderState.BlendAdd | RenderState.DepthTestAlways);
            if (useIndirect)
            {
                Bgfx.Submit(0, particleProgram, indirectBuffer);
            }
            else
            {
                Bgfx.Submit(0, particleProgram);
            }

            // done with frame
            Bgfx.Frame();
        }

        // cleanup
        if (indirectSupported)
        {
            indirectProgram.Dispose();
            indirectBuffer.Dispose();
        }

        u_params.Dispose();
        currPositionBuffer0.Dispose();
        currPositionBuffer1.Dispose();
        prevPositionBuffer0.Dispose();
        prevPositionBuffer1.Dispose();
        updateInstancesProgram.Dispose();
        initInstancesProgram.Dispose();
        particleProgram.Dispose();
        ib.Dispose();
        vb.Dispose();
    }
예제 #18
0
        public bool Render()
        {
            if (Transformations.Length == 0)
            {
                return(false);
            }
            if ((InstancedVertexBuffer == null) || (Transformations.Length > InstancedVertexBuffer.VertexCount))
            {
                if (InstancedVertexBuffer != null)
                {
                    InstancedVertexBuffer.Dispose();
                    InstancedTextureBuffer.Dispose();
                }

                InstancedVertexBuffer  = new DynamicVertexBuffer(Device, InstancedVertexDeclaration, Transformations.Length, BufferUsage.WriteOnly);
                InstancedTextureBuffer = new DynamicVertexBuffer(Device, InstancedTextureIDs, Textures.Length, BufferUsage.WriteOnly);
            }

            for (int i = 0; i < Texture2Ds.Length; i++)
            {
                Device.Textures[i] = Texture2Ds[i];
            }

            InstancedVertexBuffer.SetData <Matrix>(Transformations, 0, Transformations.Length, SetDataOptions.Discard);
            InstancedTextureBuffer.SetData <Vector2>(Textures, 0, Textures.Length, SetDataOptions.Discard);

            foreach (var mesh in Model.Meshes)
            {
                foreach (var meshPart in mesh.MeshParts)
                {
                    Device.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, 0, 0),
                        new VertexBufferBinding(InstancedVertexBuffer, 0, 1),
                        new VertexBufferBinding(InstancedTextureBuffer, 0, 1));

                    Device.Indices = meshPart.IndexBuffer;

                    InstancingShader.CurrentTechnique = InstancingShader.Techniques["HardwareInstancing"];

                    InstancingShader.Parameters["World"].SetValue(WorldMatrix);
                    InstancingShader.Parameters["View"].SetValue(Camera3D.ViewMatrix);
                    InstancingShader.Parameters["Projection"].SetValue(Camera3D.ProjectionMatrix);
                    InstancingShader.Parameters["EyePosition"].SetValue(Camera3D.CameraPosition);

                    InstancingShader.Parameters["FogEnabled"].SetValue(1.0f);
                    InstancingShader.Parameters["FogColor"].SetValue(Color.CornflowerBlue.ToVector3());
                    InstancingShader.Parameters["FogStart"].SetValue(0.0f);
                    InstancingShader.Parameters["FogEnd"].SetValue(Camera3D.RenderDistance);

                    foreach (EffectPass pass in InstancingShader.CurrentTechnique.Passes)
                    {
                        pass.Apply();
                        Device.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 1, 0, 12, Transformations.Length);
                    }
                }
            }



            return(true);
        }
예제 #19
0
        private void CalculateLightVertices(List <Vector2> rayCastHits)
        {
            vertexCount = rayCastHits.Count * 2 + 1;
            indexCount  = (rayCastHits.Count) * 9;

            //recreate arrays if they're too small or excessively large
            if (vertices == null || vertices.Length < vertexCount || vertices.Length > vertexCount * 3)
            {
                vertices = new VertexPositionColorTexture[vertexCount];
                indices  = new short[indexCount];
            }

            Vector2 drawPos = position;

            if (ParentSub != null)
            {
                drawPos += ParentSub.DrawPosition;
            }

            float cosAngle = (float)Math.Cos(Rotation);
            float sinAngle = -(float)Math.Sin(Rotation);

            Vector2 uvOffset            = Vector2.Zero;
            Vector2 overrideTextureDims = Vector2.One;

            if (OverrideLightTexture != null)
            {
                overrideTextureDims = new Vector2(OverrideLightTexture.SourceRect.Width, OverrideLightTexture.SourceRect.Height);

                Vector2 origin = OverrideLightTexture.Origin;
                if (LightSpriteEffect == SpriteEffects.FlipHorizontally)
                {
                    origin.X = OverrideLightTexture.SourceRect.Width - origin.X;
                }
                if (LightSpriteEffect == SpriteEffects.FlipVertically)
                {
                    origin.Y = OverrideLightTexture.SourceRect.Height - origin.Y;
                }
                uvOffset = (origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
            }

            // Add a vertex for the center of the mesh
            vertices[0] = new VertexPositionColorTexture(new Vector3(position.X, position.Y, 0),
                                                         Color.White, GetUV(new Vector2(0.5f, 0.5f) + uvOffset, LightSpriteEffect));

            //hacky fix to exc excessively large light volumes (they used to be up to 4x the range of the light if there was nothing to block the rays).
            //might want to tweak the raycast logic in a way that this isn't necessary
            float     boundRadius = Range * 1.1f / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
            Rectangle boundArea   = new Rectangle((int)(drawPos.X - boundRadius), (int)(drawPos.Y + boundRadius), (int)(boundRadius * 2), (int)(boundRadius * 2));

            for (int i = 0; i < rayCastHits.Count; i++)
            {
                if (MathUtils.GetLineRectangleIntersection(drawPos, rayCastHits[i], boundArea, out Vector2 intersection))
                {
                    rayCastHits[i] = intersection;
                }
            }

            // Add all the other encounter points as vertices
            // storing their world position as UV coordinates
            for (int i = 0; i < rayCastHits.Count; i++)
            {
                Vector2 vertex = rayCastHits[i];

                //we'll use the previous and next vertices to calculate the normals
                //of the two segments this vertex belongs to
                //so we can add new vertices based on these normals
                Vector2 prevVertex = rayCastHits[i > 0 ? i - 1 : rayCastHits.Count - 1];
                Vector2 nextVertex = rayCastHits[i < rayCastHits.Count - 1 ? i + 1 : 0];

                Vector2 rawDiff = vertex - drawPos;

                //calculate normal of first segment
                Vector2 nDiff1 = vertex - nextVertex;
                float   tx     = nDiff1.X; nDiff1.X = -nDiff1.Y; nDiff1.Y = tx;
                nDiff1 /= Math.Max(Math.Abs(nDiff1.X), Math.Abs(nDiff1.Y));
                //if the normal is pointing towards the light origin
                //rather than away from it, invert it
                if (Vector2.DistanceSquared(nDiff1, rawDiff) > Vector2.DistanceSquared(-nDiff1, rawDiff))
                {
                    nDiff1 = -nDiff1;
                }

                //calculate normal of second segment
                Vector2 nDiff2 = prevVertex - vertex;
                tx      = nDiff2.X; nDiff2.X = -nDiff2.Y; nDiff2.Y = tx;
                nDiff2 /= Math.Max(Math.Abs(nDiff2.X), Math.Abs(nDiff2.Y));
                //if the normal is pointing towards the light origin
                //rather than away from it, invert it
                if (Vector2.DistanceSquared(nDiff2, rawDiff) > Vector2.DistanceSquared(-nDiff2, rawDiff))
                {
                    nDiff2 = -nDiff2;
                }

                //add the normals together and use some magic numbers to create
                //a somewhat useful/good-looking blur
                Vector2 nDiff = nDiff1 + nDiff2;
                nDiff /= Math.Max(Math.Abs(nDiff.X), Math.Abs(nDiff.Y));
                nDiff *= 50.0f;

                Vector2 diff = rawDiff;
                diff /= Range * 2.0f;
                if (OverrideLightTexture != null)
                {
                    //calculate texture coordinates based on the light's rotation
                    Vector2 originDiff = diff;

                    diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle;
                    diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle;
                    diff  *= (overrideTextureDims / OverrideLightTexture.size);// / (1.0f - Math.Max(Math.Abs(uvOffset.X), Math.Abs(uvOffset.Y)));
                    diff  += uvOffset;
                }

                //finally, create the vertices
                VertexPositionColorTexture fullVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
                                                                                     Color.White, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));
                VertexPositionColorTexture fadeVert = new VertexPositionColorTexture(new Vector3(position.X + rawDiff.X + nDiff.X, position.Y + rawDiff.Y + nDiff.Y, 0),
                                                                                     Color.White * 0.0f, GetUV(new Vector2(0.5f, 0.5f) + diff, LightSpriteEffect));

                vertices[1 + i * 2]     = fullVert;
                vertices[1 + i * 2 + 1] = fadeVert;
            }

            // Compute the indices to form triangles
            for (int i = 0; i < rayCastHits.Count - 1; i++)
            {
                //main light body
                indices[i * 9]     = 0;
                indices[i * 9 + 1] = (short)((i * 2 + 3) % vertexCount);
                indices[i * 9 + 2] = (short)((i * 2 + 1) % vertexCount);

                //faded light
                indices[i * 9 + 3] = (short)((i * 2 + 1) % vertexCount);
                indices[i * 9 + 4] = (short)((i * 2 + 3) % vertexCount);
                indices[i * 9 + 5] = (short)((i * 2 + 4) % vertexCount);

                indices[i * 9 + 6] = (short)((i * 2 + 2) % vertexCount);
                indices[i * 9 + 7] = (short)((i * 2 + 1) % vertexCount);
                indices[i * 9 + 8] = (short)((i * 2 + 4) % vertexCount);
            }

            //main light body
            indices[(rayCastHits.Count - 1) * 9]     = 0;
            indices[(rayCastHits.Count - 1) * 9 + 1] = (short)(1);
            indices[(rayCastHits.Count - 1) * 9 + 2] = (short)(vertexCount - 2);

            //faded light
            indices[(rayCastHits.Count - 1) * 9 + 3] = (short)(1);
            indices[(rayCastHits.Count - 1) * 9 + 4] = (short)(vertexCount - 1);
            indices[(rayCastHits.Count - 1) * 9 + 5] = (short)(vertexCount - 2);

            indices[(rayCastHits.Count - 1) * 9 + 6] = (short)(1);
            indices[(rayCastHits.Count - 1) * 9 + 7] = (short)(2);
            indices[(rayCastHits.Count - 1) * 9 + 8] = (short)(vertexCount - 1);

            //TODO: a better way to determine the size of the vertex buffer and handle changes in size?
            //now we just create a buffer for 64 verts and make it larger if needed
            if (lightVolumeBuffer == null)
            {
                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None);
            }
            else if (vertexCount > lightVolumeBuffer.VertexCount || indexCount > lightVolumeIndexBuffer.IndexCount)
            {
                lightVolumeBuffer.Dispose();
                lightVolumeIndexBuffer.Dispose();

                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionColorTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
            }

            lightVolumeBuffer.SetData <VertexPositionColorTexture>(vertices, 0, vertexCount);
            lightVolumeIndexBuffer.SetData <short>(indices, 0, indexCount);

            Vector2 GetUV(Vector2 vert, SpriteEffects effects)
            {
                if (effects == SpriteEffects.FlipHorizontally)
                {
                    vert.X = 1.0f - vert.X;
                }
                else if (effects == SpriteEffects.FlipVertically)
                {
                    vert.Y = 1.0f - vert.Y;
                }
                else if (effects == (SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically))
                {
                    vert.X = 1.0f - vert.X;
                    vert.Y = 1.0f - vert.Y;
                }
                vert.Y = 1.0f - vert.Y;
                return(vert);
            }

            translateVertices      = Vector2.Zero;
            rotateVertices         = 0.0f;
            prevCalculatedPosition = position;
            prevCalculatedRotation = rotation;
        }
예제 #20
0
        } // AddParticle

        #endregion

        #region Dispose

        /// <summary>
        /// Dispose managed resources.
        /// </summary>
        protected override void DisposeManagedResources()
        {
            vertexBuffer.Dispose();
            indexBuffer.Dispose();
        } // DisposeManagedResources
 public void Dispose()
 {
     _effect.Dispose();
     _instanceVertexDeclaration.Dispose();
     _instanceBuffer.Dispose();
 }
        public override void DrawDistortion(LinkedList <BasicShipGameObject> ships, Camera3D DrawCamera)
        {
            if (ships.Count == 0)
            {
                return;
            }

            Game1.graphicsDevice.BlendState        = BlendState.AlphaBlend;
            Game1.graphicsDevice.DepthStencilState = DepthStencilState.None;

            if (!Applied)
            {
                ApplyEffectParameters();
            }

            DistortionEffectContainer.ViewParam.SetValue(DrawCamera.ViewMatrix);
            DistortionEffectContainer.ProjectionParam.SetValue(DrawCamera.ProjectionMatrix);
            DistortionEffectContainer.WorldParam.SetValue(ModelTransformMatrix);

            if (!DistortionBufferReady)
            {
                DistortionBufferReady = true;
                Array.Resize(ref DistortionShipVertecies, ships.Count);
                int i = 0;
                foreach (BasicShipGameObject s in ships)
                {
                    DistortionShipVertecies[i].WorldMatrix = s.WorldMatrix;
                    DistortionShipVertecies[i++].color     = s.MyColor;
                }

                if ((DistortionvertexBuffer == null) ||
                    (ships.Count > DistortionvertexBuffer.VertexCount))
                {
                    if (DistortionvertexBuffer != null)
                    {
                        DistortionvertexBuffer.Dispose();
                    }

                    DistortionvertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, ShipVertex.shipVertexDeclaration,
                                                                     DistortionShipVertecies.Length, BufferUsage.WriteOnly);
                }

                DistortionvertexBuffer.SetData(DistortionShipVertecies, 0, DistortionShipVertecies.Length, SetDataOptions.Discard);
            }
            else if (DistortionvertexBuffer.IsContentLost)
            {
                DistortionvertexBuffer.SetData(DistortionShipVertecies, 0, DistortionShipVertecies.Length, SetDataOptions.Discard);
            }

            foreach (ModelMesh mesh in ShipModel.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    Game1.graphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                        new VertexBufferBinding(DistortionvertexBuffer, 0, 1)
                        );

                    Game1.graphicsDevice.Indices = meshPart.IndexBuffer;

                    foreach (EffectPass pass in DistortionEffectContainer.DistortionEffect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                                     meshPart.NumVertices, meshPart.StartIndex,
                                                                     meshPart.PrimitiveCount, DistortionShipVertecies.Length);
                    }
                }
            }
        }
예제 #23
0
 protected override void OnDispose()
 {
     transformBuffer.Dispose();
     colorBuffer.Dispose();
     textureCoordBuffer.Dispose();
 }
예제 #24
0
        private void CalculateLightVertices(List <Vector2> rayCastHits)
        {
            List <VertexPositionTexture> vertices = new List <VertexPositionTexture>();

            Vector2 drawPos = position;

            if (ParentSub != null)
            {
                drawPos += ParentSub.DrawPosition;
            }

            float cosAngle = (float)Math.Cos(Rotation);
            float sinAngle = -(float)Math.Sin(Rotation);

            Vector2 uvOffset            = Vector2.Zero;
            Vector2 overrideTextureDims = Vector2.One;

            if (overrideLightTexture != null)
            {
                overrideTextureDims = new Vector2(overrideLightTexture.SourceRect.Width, overrideLightTexture.SourceRect.Height);
                uvOffset            = (overrideLightTexture.Origin / overrideTextureDims) - new Vector2(0.5f, 0.5f);
            }

            // Add a vertex for the center of the mesh
            vertices.Add(new VertexPositionTexture(new Vector3(position.X, position.Y, 0),
                                                   new Vector2(0.5f, 0.5f) + uvOffset));

            // Add all the other encounter points as vertices
            // storing their world position as UV coordinates
            foreach (Vector2 vertex in rayCastHits)
            {
                Vector2 rawDiff = vertex - drawPos;
                Vector2 diff    = rawDiff;
                diff /= range * 2.0f;
                if (overrideLightTexture != null)
                {
                    Vector2 originDiff = diff;

                    diff.X = originDiff.X * cosAngle - originDiff.Y * sinAngle;
                    diff.Y = originDiff.X * sinAngle + originDiff.Y * cosAngle;
                    diff  *= (overrideTextureDims / overrideLightTexture.size) * 2.0f;

                    diff += uvOffset;
                }

                vertices.Add(new VertexPositionTexture(new Vector3(position.X + rawDiff.X, position.Y + rawDiff.Y, 0),
                                                       new Vector2(0.5f, 0.5f) + diff));
            }

            // Compute the indices to form triangles
            List <short> indices = new List <short>();

            for (int i = 0; i < rayCastHits.Count - 1; i++)
            {
                indices.Add(0);
                indices.Add((short)((i + 2) % vertices.Count));
                indices.Add((short)((i + 1) % vertices.Count));
            }

            indices.Add(0);
            indices.Add((short)(1));
            indices.Add((short)(vertices.Count - 1));

            vertexCount = vertices.Count;
            indexCount  = indices.Count;

            //TODO: a better way to determine the size of the vertex buffer and handle changes in size?
            //now we just create a buffer for 64 verts and make it larger if needed
            if (lightVolumeBuffer == null)
            {
                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, Math.Max(64, (int)(vertexCount * 1.5)), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), Math.Max(64 * 3, (int)(indexCount * 1.5)), BufferUsage.None);
            }
            else if (vertexCount > lightVolumeBuffer.VertexCount)
            {
                lightVolumeBuffer.Dispose();
                lightVolumeIndexBuffer.Dispose();

                lightVolumeBuffer      = new DynamicVertexBuffer(GameMain.Instance.GraphicsDevice, VertexPositionTexture.VertexDeclaration, (int)(vertexCount * 1.5), BufferUsage.None);
                lightVolumeIndexBuffer = new DynamicIndexBuffer(GameMain.Instance.GraphicsDevice, typeof(short), (int)(indexCount * 1.5), BufferUsage.None);
            }

            lightVolumeBuffer.SetData <VertexPositionTexture>(vertices.ToArray());
            lightVolumeIndexBuffer.SetData <short>(indices.ToArray());
        }
예제 #25
0
 protected override void DisposeNative()
 {
     nativeVertexBuffer.Dispose();
     nativeIndexBuffer.Dispose();
 }
예제 #26
0
 public void Dispose()
 {
     vertexBuffer.Dispose();
     particles = null;
 }
        public void DrawInstanced(Camera3D DrawCamera)
        {
            if (BulletCount == 0)
            {
                return;
            }

            ViewParam.SetValue(DrawCamera.ViewMatrix);
            ProjectionParam.SetValue(DrawCamera.ProjectionMatrix);
            WorldParam.SetValue(Matrix.Identity);
            ShipEffect.CurrentTechnique = ForwardInstancedTechnique;

            if (!BufferReady)
            {
                BufferReady = true;
                Array.Resize(ref ModelTransforms, Bullets.Count);
                int i = 0;
                foreach (Bullet s in Bullets)
                {
                    ModelTransforms[i++] = s.WorldMatrix;
                }

                if ((vertexBuffer == null) ||
                    (Bullets.Count > vertexBuffer.VertexCount))
                {
                    if (vertexBuffer != null)
                    {
                        vertexBuffer.Dispose();
                    }

                    vertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, instanceVertexDeclaration,
                                                           ModelTransforms.Length, BufferUsage.WriteOnly);
                }

                vertexBuffer.SetData(ModelTransforms, 0, ModelTransforms.Length, SetDataOptions.Discard);
            }
            else if (vertexBuffer.IsContentLost)
            {
                vertexBuffer.SetData(ModelTransforms, 0, ModelTransforms.Length, SetDataOptions.Discard);
            }

            foreach (ModelMesh mesh in BulletModel.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    Game1.graphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                        new VertexBufferBinding(vertexBuffer, 0, 1)
                        );

                    Game1.graphicsDevice.Indices = meshPart.IndexBuffer;

                    foreach (EffectPass pass in ShipEffect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                                     meshPart.NumVertices, meshPart.StartIndex,
                                                                     meshPart.PrimitiveCount, ModelTransforms.Length);
                    }
                }
            }
        }
예제 #28
0
        public void DrawInstanced(Camera3D DrawCamera)
        {
            if (UnitChildren.Count == 0)
            {
                return;
            }

            Game1.graphicsDevice.BlendState        = BlendState.Additive;
            Game1.graphicsDevice.DepthStencilState = DepthStencilState.None;

            if (!Applied)
            {
                ApplyEffectParameters();
            }

            ViewParam.SetValue(DrawCamera.ViewMatrix);
            ProjectionParam.SetValue(DrawCamera.ProjectionMatrix);
            ViewPosParam.SetValue(DrawCamera.Position);

            if (!BufferReady)
            {
                BufferReady = true;
                Array.Resize(ref ShieldVertecies, UnitChildren.Count);
                int i = 0;
                foreach (UnitBasic s in UnitChildren)
                {
                    ShieldVertecies[i].WorldMatrix = s.WorldMatrix;
                    ShieldVertecies[i].color       = s.GetShieldColor() * 0.5f;

                    i++;
                }

                if ((vertexBuffer == null) ||
                    (UnitChildren.Count > vertexBuffer.VertexCount))
                {
                    if (vertexBuffer != null)
                    {
                        vertexBuffer.Dispose();
                    }

                    vertexBuffer = new DynamicVertexBuffer(Game1.graphicsDevice, ShieldVertex.shieldVertexDeclaration,
                                                           ShieldVertecies.Length, BufferUsage.WriteOnly);
                }

                vertexBuffer.SetData(ShieldVertecies, 0, ShieldVertecies.Length, SetDataOptions.Discard);
            }
            else if (vertexBuffer.IsContentLost)
            {
                vertexBuffer.SetData(ShieldVertecies, 0, ShieldVertecies.Length, SetDataOptions.Discard);
            }

            foreach (ModelMesh mesh in ShieldModel.Meshes)
            {
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                {
                    Game1.graphicsDevice.SetVertexBuffers(
                        new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                        new VertexBufferBinding(vertexBuffer, 0, 1)
                        );

                    Game1.graphicsDevice.Indices = meshPart.IndexBuffer;

                    foreach (EffectPass pass in ShieldEffect.CurrentTechnique.Passes)
                    {
                        pass.Apply();

                        Game1.graphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                                     meshPart.NumVertices, meshPart.StartIndex,
                                                                     meshPart.PrimitiveCount, ShieldVertecies.Length);
                    }
                }
            }


            Game1.graphicsDevice.BlendState = BlendState.AlphaBlend;
        }
예제 #29
0
        /// <summary>
        /// Resets the vertex buffer object from the verticies.
        /// <param Name="device">GPU to draw with.</param></summary>
        public virtual void ResetBuffer(GraphicsDevice device)
        {
            //if(DwarfGame.ExitGame)
            //{
            //    return;
            //}

            //lock (VertexLock)
            {
                if (VertexBuffer != null && !VertexBuffer.IsDisposed)
                {
                    VertexBuffer.Dispose();
                }
                VertexBuffer = null;

                if (IndexBuffer != null && !IndexBuffer.IsDisposed)
                {
                    IndexBuffer.Dispose();
                }
                IndexBuffer = null;

                if (IndexCount <= 0 && Indexes != null)
                {
                    IndexCount = Indexes.Length;
                }

                if (VertexCount <= 0 && Vertices != null)
                {
                    VertexCount = Vertices.Length;
                }



                if (Vertices != null)
                {
                    try
                    {
                        DynamicVertexBuffer newBuff = new DynamicVertexBuffer(device, ExtendedVertex.VertexDeclaration, Vertices.Length,
                                                                              BufferUsage.WriteOnly);
                        newBuff.SetData(Vertices, 0, VertexCount);
                        VertexBuffer = newBuff;
                    }
                    catch (Exception exception)
                    {
                        Console.Out.WriteLine(exception.ToString());
                        VertexBuffer = null;
                    }
                }

                if (Indexes != null)
                {
                    try
                    {
                        DynamicIndexBuffer newIndexBuff = new DynamicIndexBuffer(device, typeof(ushort), Indexes.Length, BufferUsage.None);
                        newIndexBuff.SetData(Indexes, 0, IndexCount);
                        IndexBuffer = newIndexBuff;
                    }
                    catch (Exception exception)
                    {
                        Console.Out.WriteLine(exception.ToString());
                        IndexBuffer = null;
                    }
                }
            }
        }
예제 #30
0
 protected override void OnDispose()
 {
     vertexPositionBuffer.Dispose();
     transformBuffer.Dispose();
     colorBuffer.Dispose();
 }
예제 #31
0
        public void FlushRequests(IGameContext gameContext, IRenderContext renderContext)
        {
            LastBatchCount     = 0;
            LastApplyCount     = 0;
            LastBatchSaveCount = 0;

            if (renderContext.IsCurrentRenderPass <I3DBatchedRenderPass>())
            {
                using (_profiler.Measure("render-flush"))
                {
                    foreach (var kv in _requestLookup)
                    {
                        if (_requestInstances[kv.Key].Count == 0)
                        {
                            continue;
                        }

                        LastBatchCount++;
                        LastBatchSaveCount += (ulong)(_requestInstances[kv.Key].Count - 1);

                        var request = kv.Value;

                        int pc;
                        SetupForRequest(renderContext, request, out pc, false);
                        request.Effect.NativeEffect.Parameters["View"]?.SetValue(renderContext.View);
                        request.Effect.NativeEffect.Parameters["Projection"]?.SetValue(renderContext.Projection);

                        List <Matrix> filteredInstances;
                        if (kv.Value.BoundingRegion != null)
                        {
                            // TODO: Reduce allocations here.
                            filteredInstances = new List <Matrix>(_requestInstances[kv.Key].Count);
                            foreach (var ri in _requestInstances[kv.Key])
                            {
                                if (kv.Value.BoundingRegion.Intersects(renderContext.BoundingFrustum, Vector3.Transform(Vector3.Zero, ri)))
                                {
                                    filteredInstances.Add(ri);
                                }
                            }

                            if (filteredInstances.Count == 0)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            filteredInstances = _requestInstances[kv.Key];
                        }

#if PLATFORM_WINDOWS
                        var allowInstancedCalls = true;
#else
                        var allowInstancedCalls = false;
#endif

                        if (allowInstancedCalls &&
                            request.Effect.NativeEffect.Techniques[request.TechniqueName + "Batched"] != null)
                        {
#if PLATFORM_WINDOWS
                            if (_vertexBuffer == null ||
                                filteredInstances.Count > _vertexBufferLastInstanceCount)
                            {
                                _vertexBuffer?.Dispose();

                                _vertexBuffer = new DynamicVertexBuffer(
                                    renderContext.GraphicsDevice,
                                    _vertexDeclaration,
                                    filteredInstances.Count,
                                    BufferUsage.WriteOnly);
                                _vertexBufferLastInstanceCount = filteredInstances.Count;
                            }

                            _vertexBuffer.SetData(filteredInstances.ToArray(), 0, filteredInstances.Count);
                            renderContext.GraphicsDevice.SetVertexBuffers(
                                new VertexBufferBinding(request.MeshVertexBuffer),
                                new VertexBufferBinding(_vertexBuffer, 0, 1));

                            foreach (var pass in request.Effect.NativeEffect.Techniques[request.TechniqueName + "Batched"].Passes)
                            {
                                pass.Apply();

                                renderContext.GraphicsDevice.DrawInstancedPrimitives(
                                    request.PrimitiveType,
                                    0,
                                    0,
                                    pc,
                                    filteredInstances.Count);
                            }
#endif
                        }
                        else
                        {
                            // If there's less than 5 instances, just push the draw calls to the GPU.
                            if (filteredInstances.Count <= 5 || !request.SupportsComputingInstancesToCustomBuffers)
                            {
                                renderContext.GraphicsDevice.SetVertexBuffer(request.MeshVertexBuffer);

                                foreach (var instance in filteredInstances)
                                {
                                    request.Effect.NativeEffect.Parameters["World"]?.SetValue(instance);

                                    foreach (var pass in request.Effect.NativeEffect.Techniques[request.TechniqueName].Passes)
                                    {
                                        pass.Apply();

                                        LastApplyCount++;

                                        renderContext.GraphicsDevice.DrawIndexedPrimitives(
                                            request.PrimitiveType,
                                            0,
                                            0,
                                            pc);
                                    }
                                }
                            }
                            else
                            {
                                var buffersNeedComputing = false;
                                var vertexBuffer         = _renderAutoCache.AutoCache("renderbatcher-" + kv.Key, new object[]
                                {
                                    filteredInstances.Count,
                                    request.MeshVertexBuffer.VertexCount,
                                    request.MeshVertexBuffer.VertexDeclaration
                                }, gameContext, () =>
                                {
                                    buffersNeedComputing = true;
                                    return(new VertexBuffer(
                                               renderContext.GraphicsDevice,
                                               request.MeshVertexBuffer.VertexDeclaration,
                                               filteredInstances.Count * request.MeshVertexBuffer.VertexCount,
                                               BufferUsage.WriteOnly));
                                });
                                var indexBuffer = _renderAutoCache.AutoCache("renderbatcher-" + kv.Key, new object[]
                                {
                                    filteredInstances.Count,
                                    request.MeshVertexBuffer.VertexCount,
                                }, gameContext, () =>
                                {
                                    buffersNeedComputing = true;
                                    return(new IndexBuffer(
                                               renderContext.GraphicsDevice,
                                               IndexElementSize.ThirtyTwoBits,
                                               filteredInstances.Count * request.MeshIndexBuffer.IndexCount,
                                               BufferUsage.WriteOnly));
                                });

                                if (buffersNeedComputing)
                                {
                                    // Compute a pre-transformed vertex and index buffer for rendering.
                                    request.ComputeInstancesToCustomBuffers(
                                        filteredInstances,
                                        vertexBuffer,
                                        indexBuffer);
                                }

                                renderContext.GraphicsDevice.SetVertexBuffer(vertexBuffer);
                                renderContext.GraphicsDevice.Indices = indexBuffer;
                                request.Effect.NativeEffect.Parameters["World"]?.SetValue(Matrix.Identity);

                                foreach (
                                    var pass in
                                    request.Effect.NativeEffect.Techniques[request.TechniqueName].Passes
                                    )
                                {
                                    pass.Apply();

                                    renderContext.GraphicsDevice.DrawIndexedPrimitives(
                                        request.PrimitiveType,
                                        0,
                                        0,
                                        pc * filteredInstances.Count);
                                }
                            }
                        }

                        filteredInstances.Clear();
                    }

                    _requestLookup.Clear();
                    _requestInstances.Clear();
                }
            }
        }