public DynamicInstancedMeshGeometry(int maxInstances, IDrawBatch geometry)
		{
			instanceMatrices = new Matrix[maxInstances];

			//create a sphere for the geometry, as it implements IDrawBatch already
			this.geometry = geometry;
		}
示例#2
0
        public InstancedMeshGeometry(int maxInstances)
        {
            instanceMatrices = new Matrix[maxInstances];

            //create a sphere for the geometry, as it implements IDrawBatch already
            geometry = new Xen.Ex.Geometry.Sphere(Vector3.One, 2, true, false, false);
        }
示例#3
0
 public bool CanAppend(IDrawBatch other)
 {
     return
         (other.VertexMode == this.vertexMode &&
          other is DrawBatch <T> &&
          IsVertexModeAppendable(this.VertexMode) &&
          other.Material == this.material);
 }
示例#4
0
 public bool CanAppend(IDrawBatch other)
 {
     return
         (other.VertexMode == this.vertexMode &&
          other is DrawBatch <T> &&
          this.vertexMode.IsBatchableMode() &&
          other.Material == this.material);
 }
示例#5
0
        private int RenderBatches(List <IDrawBatch> buffer)
        {
            if (this.pickingIndex == 0)
            {
                Profile.TimeProcessDrawcalls.BeginMeasure();
            }

            int drawCalls = 0;
            List <IDrawBatch> batchesSharingVBO = new List <IDrawBatch>();
            IDrawBatch        lastBatchRendered = null;

            IDrawBatch lastBatch = null;

            for (int i = 0; i < buffer.Count; i++)
            {
                IDrawBatch currentBatch = buffer[i];
                IDrawBatch nextBatch    = (i < buffer.Count - 1) ? buffer[i + 1] : null;

                if (lastBatch == null || lastBatch.CanShareVBO(currentBatch))
                {
                    batchesSharingVBO.Add(currentBatch);
                }

                if (batchesSharingVBO.Count > 0 && (nextBatch == null || !currentBatch.CanShareVBO(nextBatch)))
                {
                    int vertexOffset = 0;
                    batchesSharingVBO[0].UploadToVBO(batchesSharingVBO);
                    drawCalls++;

                    foreach (IDrawBatch renderBatch in batchesSharingVBO)
                    {
                        renderBatch.SetupVBO();
                        renderBatch.Render(this, ref vertexOffset, ref lastBatchRendered);
                        renderBatch.FinishVBO();
                        drawCalls++;
                    }

                    batchesSharingVBO.Clear();
                    lastBatch = null;
                }
                else
                {
                    lastBatch = currentBatch;
                }
            }

            if (lastBatchRendered != null)
            {
                lastBatchRendered.FinishRendering();
            }

            if (this.pickingIndex == 0)
            {
                Profile.TimeProcessDrawcalls.EndMeasure();
            }
            return(drawCalls);
        }
示例#6
0
        void IGraphicsBackend.Render(IReadOnlyList <IDrawBatch> batches)
        {
            IDrawBatch lastBatchRendered = null;
            IDrawBatch lastBatch         = null;
            int        drawCalls         = 0;

            this.renderBatchesSharingVBO.Clear();
            for (int i = 0; i < batches.Count; i++)
            {
                IDrawBatch currentBatch = batches[i];
                IDrawBatch nextBatch    = (i < batches.Count - 1) ? batches[i + 1] : null;

                if (lastBatch == null || lastBatch.SameVertexType(currentBatch))
                {
                    this.renderBatchesSharingVBO.Add(currentBatch);
                }

                if (this.renderBatchesSharingVBO.Count > 0 && (nextBatch == null || !currentBatch.SameVertexType(nextBatch)))
                {
                    int vertexOffset = 0;
                    this.renderBatchesSharingVBO[0].UploadVertices(this, this.renderBatchesSharingVBO);
                    drawCalls++;

                    foreach (IDrawBatch batch in this.renderBatchesSharingVBO)
                    {
                        drawCalls++;

                        this.PrepareRenderBatch(batch);
                        this.RenderBatch(batch, vertexOffset, lastBatchRendered);
                        this.FinishRenderBatch(batch);

                        vertexOffset     += batch.VertexCount;
                        lastBatchRendered = batch;
                    }

                    this.renderBatchesSharingVBO.Clear();
                    lastBatch = null;
                }
                else
                {
                    lastBatch = currentBatch;
                }
            }

            if (lastBatchRendered != null)
            {
                this.FinishMaterial(lastBatchRendered.Material);
            }

            if (this.renderStats != null)
            {
                this.renderStats.DrawCalls += drawCalls;
            }
        }
示例#7
0
        private void RenderBatch(IDrawBatch renderBatch, int vertexOffset, IDrawBatch lastBatchRendered)
        {
            if (lastBatchRendered == null || lastBatchRendered.Material != renderBatch.Material)
            {
                this.SetupMaterial(renderBatch.Material, lastBatchRendered == null ? null : lastBatchRendered.Material);
            }

            GL.DrawArrays(GetOpenTKVertexMode(renderBatch.VertexMode), vertexOffset, renderBatch.VertexCount);

            lastBatchRendered = renderBatch;
        }
示例#8
0
        public void Render(IDrawDevice device, ref int vertexOffset, ref IDrawBatch lastBatchRendered)
        {
            if (lastBatchRendered == null || lastBatchRendered.Material != this.material)
            {
                this.material.SetupForRendering(device, lastBatchRendered == null ? null : lastBatchRendered.Material);
            }

            GL.DrawArrays((PrimitiveType)this.vertexMode, vertexOffset, this.vertexCount);

            vertexOffset     += this.vertexCount;
            lastBatchRendered = this;
        }
示例#9
0
        public void AddBatch(IDrawBatch drawBatch)
        {
            if (drawBatch.VertexCount == 0)
            {
                return;
            }

            BatchInfo material = drawBatch.Material;

            if (material.Technique == null || !material.Technique.IsAvailable)
            {
                material           = new BatchInfo(material);
                material.Technique = DrawTechnique.Solid;
            }
            else if (material.Technique.Res.NeedsPreprocess)
            {
                material = new BatchInfo(material);
                material.Technique.Res.PreprocessBatch(this, drawBatch);
                if (material.Technique == null || !material.Technique.IsAvailable)
                {
                    material.Technique = DrawTechnique.Solid;
                }
            }

            // When rendering without depth writing, use z sorting everywhere - there's no real depth buffering!
            bool zSort = !this.DepthWrite || material.Technique.Res.NeedsZSort;
            List <IDrawBatch> buffer = zSort ? this.drawBufferZSort : this.drawBuffer;

            drawBatch.CalcZSortIndex();

            if (buffer.Count > 0 && buffer[buffer.Count - 1].CanAppend(drawBatch))
            {
                buffer[buffer.Count - 1].Append(drawBatch);
            }
            else
            {
                buffer.Add(drawBatch);
            }
            ++this.numRawBatches;
        }
示例#10
0
 private int DrawBatchComparerZSort(IDrawBatch first, IDrawBatch second)
 {
     if (second.ZSortIndex < first.ZSortIndex)
     {
         return(-1);
     }
     if (second.ZSortIndex > first.ZSortIndex)
     {
         return(1);
     }
     if (second.ZSortIndex == first.ZSortIndex)
     {
         return(0);
     }
     if (float.IsNaN(second.ZSortIndex))
     {
         return(float.IsNaN(first.ZSortIndex) ? 0 : -1);
     }
     else
     {
         return(1);
     }
 }
示例#11
0
        private List <IDrawBatch> OptimizeBatches(List <IDrawBatch> sortedBuffer)
        {
            List <IDrawBatch> optimized = new List <IDrawBatch>(sortedBuffer.Count);
            IDrawBatch        current   = sortedBuffer[0];
            IDrawBatch        next;

            optimized.Add(current);
            for (int i = 1; i < sortedBuffer.Count; i++)
            {
                next = sortedBuffer[i];

                if (current.CanAppend(next))
                {
                    current.Append(next);
                }
                else
                {
                    current = next;
                    optimized.Add(current);
                }
            }

            return(optimized);
        }
示例#12
0
 private int DrawBatchComparer(IDrawBatch first, IDrawBatch second)
 {
     return(first.SortIndex - second.SortIndex);
 }
示例#13
0
        private void FinishRenderBatch(IDrawBatch renderBatch)
        {
            DrawTechnique       technique = renderBatch.Material.Technique.Res ?? DrawTechnique.Solid.Res;
            NativeShaderProgram program   = (technique.Shader.Res != null ? technique.Shader.Res.Native : null) as NativeShaderProgram;

            VertexDeclaration vertexDeclaration = renderBatch.VertexDeclaration;

            VertexElement[] elements = vertexDeclaration.Elements;

            for (int elementIndex = 0; elementIndex < elements.Length; elementIndex++)
            {
                switch (elements[elementIndex].Role)
                {
                case VertexElementRole.Position:
                {
                    GL.DisableClientState(ArrayCap.VertexArray);
                    break;
                }

                case VertexElementRole.TexCoord:
                {
                    GL.DisableClientState(ArrayCap.TextureCoordArray);
                    break;
                }

                case VertexElementRole.Color:
                {
                    GL.DisableClientState(ArrayCap.ColorArray);
                    break;
                }

                default:
                {
                    if (program != null)
                    {
                        ShaderFieldInfo[] varInfo   = program.Fields;
                        int[]             locations = program.FieldLocations;

                        int selectedVar = -1;
                        for (int varIndex = 0; varIndex < varInfo.Length; varIndex++)
                        {
                            if (locations[varIndex] == -1)
                            {
                                continue;
                            }
                            if (!ShaderVarMatches(
                                    ref varInfo[varIndex],
                                    elements[elementIndex].Type,
                                    elements[elementIndex].Count))
                            {
                                continue;
                            }

                            selectedVar = varIndex;
                            break;
                        }
                        if (selectedVar == -1)
                        {
                            break;
                        }

                        GL.DisableVertexAttribArray(locations[selectedVar]);
                    }
                    break;
                }
                }
            }
        }
		public StaticInstancedMeshGeometry(int maxInstances, IDrawBatch geometry)
		{
			this.geometry = geometry;

			//setup the data for static instancing
			//create the static instance buffer
			this.staticInstanceBuffer = new InstanceBuffer(maxInstances);
		}
示例#15
0
        private void PrepareRenderBatch(IDrawBatch renderBatch)
        {
            DrawTechnique       technique = renderBatch.Material.Technique.Res ?? DrawTechnique.Solid.Res;
            NativeShaderProgram program   = (technique.Shader.Res != null ? technique.Shader.Res.Native : null) as NativeShaderProgram;

            VertexDeclaration vertexDeclaration = renderBatch.VertexDeclaration;

            VertexElement[] elements = vertexDeclaration.Elements;

            for (int elementIndex = 0; elementIndex < elements.Length; elementIndex++)
            {
                switch (elements[elementIndex].Role)
                {
                case VertexElementRole.Position:
                {
                    GL.EnableClientState(ArrayCap.VertexArray);
                    GL.VertexPointer(
                        elements[elementIndex].Count,
                        VertexPointerType.Float,
                        vertexDeclaration.Size,
                        elements[elementIndex].Offset);
                    break;
                }

                case VertexElementRole.TexCoord:
                {
                    GL.EnableClientState(ArrayCap.TextureCoordArray);
                    GL.TexCoordPointer(
                        elements[elementIndex].Count,
                        TexCoordPointerType.Float,
                        vertexDeclaration.Size,
                        elements[elementIndex].Offset);
                    break;
                }

                case VertexElementRole.Color:
                {
                    ColorPointerType attribType;
                    switch (elements[elementIndex].Type)
                    {
                    default:
                    case VertexElementType.Float: attribType = ColorPointerType.Float; break;

                    case VertexElementType.Byte: attribType = ColorPointerType.UnsignedByte; break;
                    }

                    GL.EnableClientState(ArrayCap.ColorArray);
                    GL.ColorPointer(
                        elements[elementIndex].Count,
                        attribType,
                        vertexDeclaration.Size,
                        elements[elementIndex].Offset);
                    break;
                }

                default:
                {
                    if (program != null)
                    {
                        ShaderFieldInfo[] varInfo   = program.Fields;
                        int[]             locations = program.FieldLocations;

                        int selectedVar = -1;
                        for (int varIndex = 0; varIndex < varInfo.Length; varIndex++)
                        {
                            if (locations[varIndex] == -1)
                            {
                                continue;
                            }
                            if (!ShaderVarMatches(
                                    ref varInfo[varIndex],
                                    elements[elementIndex].Type,
                                    elements[elementIndex].Count))
                            {
                                continue;
                            }

                            selectedVar = varIndex;
                            break;
                        }
                        if (selectedVar == -1)
                        {
                            break;
                        }

                        VertexAttribPointerType attribType;
                        switch (elements[elementIndex].Type)
                        {
                        default:
                        case VertexElementType.Float: attribType = VertexAttribPointerType.Float; break;

                        case VertexElementType.Byte: attribType = VertexAttribPointerType.UnsignedByte; break;
                        }

                        GL.EnableVertexAttribArray(locations[selectedVar]);
                        GL.VertexAttribPointer(
                            locations[selectedVar],
                            elements[elementIndex].Count,
                            attribType,
                            false,
                            vertexDeclaration.Size,
                            elements[elementIndex].Offset);
                    }
                    break;
                }
                }
            }
        }
示例#16
0
 public bool SameVertexType(IDrawBatch other)
 {
     return(other is DrawBatch <T>);
 }
示例#17
0
        public void AddVertices <T>(BatchInfo material, VertexMode vertexMode, T[] vertexBuffer, int vertexCount) where T : struct, IVertexData
        {
            if (vertexCount == 0)
            {
                return;
            }
            if (vertexBuffer == null || vertexBuffer.Length == 0)
            {
                return;
            }
            if (vertexCount > vertexBuffer.Length)
            {
                vertexCount = vertexBuffer.Length;
            }
            if (material == null)
            {
                material = Material.Checkerboard.Res.InfoDirect;
            }

            if (this.pickingIndex != 0)
            {
                ColorRgba clr = new ColorRgba((this.pickingIndex << 8) | 0xFF);
                for (int i = 0; i < vertexCount; ++i)
                {
                    vertexBuffer[i].Color = clr;
                }

                material           = new BatchInfo(material);
                material.Technique = DrawTechnique.Picking;
                if (material.Textures == null)
                {
                    material.MainTexture = Texture.White;
                }
            }
            else if (material.Technique == null || !material.Technique.IsAvailable)
            {
                material           = new BatchInfo(material);
                material.Technique = DrawTechnique.Solid;
            }

            // When rendering without depth writing, use z sorting everywhere - there's no real depth buffering!
            bool zSort = !this.DepthWrite || material.Technique.Res.NeedsZSort;
            List <IDrawBatch> buffer     = zSort ? this.drawBufferZSort : this.drawBuffer;
            float             zSortIndex = zSort ? DrawBatch <T> .CalcZSortIndex(vertexBuffer, vertexCount) : 0.0f;

            // Determine if we can append the incoming vertices into the previous batch
            IDrawBatch prevBatch = buffer.Count > 0 ? buffer[buffer.Count - 1] : null;

            if (prevBatch != null &&
                // ToDo: Move into CanAppendJIT on next major version step:
                // Make sure to not generate batches that will be in the Large Object Heap (>= 85k bytes)
                // because this will trigger lots and lots of Gen2 collections over time.
                vertexCount + prevBatch.VertexCount < 1024 &&
                // Check if the batches do match enough for being merged
                prevBatch.CanAppendJIT <T>(
                    zSort ? 1.0f : 0.0f,                     // Obsolete as of 2016-06-17, can be replcaed with zSort bool.
                    zSortIndex,
                    material,
                    vertexMode))
            {
                prevBatch.AppendJIT(vertexBuffer, vertexCount);
            }
            else
            {
                buffer.Add(new DrawBatch <T>(material, vertexMode, vertexBuffer, vertexCount, zSortIndex));
            }
            ++this.numRawBatches;
        }
示例#18
0
 public bool CanShareVBO(IDrawBatch other)
 {
     return(other is DrawBatch <T>);
 }
示例#19
0
 private int DrawBatchComparerZSort(IDrawBatch first, IDrawBatch second)
 {
     return(MathF.RoundToInt((second.ZSortIndex - first.ZSortIndex) * this.zSortAccuracy));
 }
示例#20
0
 public void Append(IDrawBatch other)
 {
     this.Append((DrawBatch <T>)other);
 }
示例#21
0
 /// <summary>
 /// Performs a preprocessing operation for an incoming batch. Does nothing by default but may be overloaded, if needed.
 /// </summary>
 /// <typeparam name="T">The incoming vertex type</typeparam>
 /// <param name="device"></param>
 /// <param name="material"><see cref="Duality.Resources.Material"/> information for the current batch.</param>
 public virtual void PreprocessBatch(IDrawDevice device, IDrawBatch drawBatch)
 {
 }