public DynamicInstancedMeshGeometry(int maxInstances, IDrawBatch geometry) { instanceMatrices = new Matrix[maxInstances]; //create a sphere for the geometry, as it implements IDrawBatch already this.geometry = geometry; }
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); }
public bool CanAppend(IDrawBatch other) { return (other.VertexMode == this.vertexMode && other is DrawBatch <T> && IsVertexModeAppendable(this.VertexMode) && other.Material == this.material); }
public bool CanAppend(IDrawBatch other) { return (other.VertexMode == this.vertexMode && other is DrawBatch <T> && this.vertexMode.IsBatchableMode() && other.Material == this.material); }
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); }
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; } }
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; }
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; }
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; }
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); } }
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); }
private int DrawBatchComparer(IDrawBatch first, IDrawBatch second) { return(first.SortIndex - second.SortIndex); }
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); }
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; } } } }
public bool SameVertexType(IDrawBatch other) { return(other is DrawBatch <T>); }
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; }
public bool CanShareVBO(IDrawBatch other) { return(other is DrawBatch <T>); }
private int DrawBatchComparerZSort(IDrawBatch first, IDrawBatch second) { return(MathF.RoundToInt((second.ZSortIndex - first.ZSortIndex) * this.zSortAccuracy)); }
public void Append(IDrawBatch other) { this.Append((DrawBatch <T>)other); }
/// <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) { }