public void Draw(Skeleton skeleton) { var drawOrder = skeleton.DrawOrder; var drawOrderItems = skeleton.DrawOrder.Items; float skeletonR = skeleton.R, skeletonG = skeleton.G, skeletonB = skeleton.B, skeletonA = skeleton.A; Color color = new Color(); if (VertexEffect != null) { VertexEffect.Begin(skeleton); } for (int i = 0, n = drawOrder.Count; i < n; i++) { Slot slot = drawOrderItems[i]; Attachment attachment = slot.Attachment; float attachmentZOffset = zSpacing * i; float attachmentColorR, attachmentColorG, attachmentColorB, attachmentColorA; object textureObject = null; int verticesCount = 0; float[] vertices = this.vertices; int indicesCount = 0; int[] indices = null; float[] uvs = null; if (attachment is RegionAttachment) { RegionAttachment regionAttachment = (RegionAttachment)attachment; attachmentColorR = regionAttachment.R; attachmentColorG = regionAttachment.G; attachmentColorB = regionAttachment.B; attachmentColorA = regionAttachment.A; AtlasRegion region = (AtlasRegion)regionAttachment.RendererObject; textureObject = region.page.rendererObject; verticesCount = 4; regionAttachment.ComputeWorldVertices(slot.Bone, vertices, 0, 2); indicesCount = 6; indices = quadTriangles; uvs = regionAttachment.UVs; } else if (attachment is MeshAttachment) { MeshAttachment mesh = (MeshAttachment)attachment; attachmentColorR = mesh.R; attachmentColorG = mesh.G; attachmentColorB = mesh.B; attachmentColorA = mesh.A; AtlasRegion region = (AtlasRegion)mesh.RendererObject; textureObject = region.page.rendererObject; int vertexCount = mesh.WorldVerticesLength; if (vertices.Length < vertexCount) { vertices = new float[vertexCount]; } verticesCount = vertexCount >> 1; mesh.ComputeWorldVertices(slot, vertices); indicesCount = mesh.Triangles.Length; indices = mesh.Triangles; uvs = mesh.UVs; } else if (attachment is ClippingAttachment) { ClippingAttachment clip = (ClippingAttachment)attachment; clipper.ClipStart(slot, clip); continue; } else { continue; } // set blend state BlendState blendState = new BlendState(); Blend blendSrc; Blend blendDst; if (premultipliedAlpha) { blendState.AlphaBlendFunction = BlendState.AlphaBlend.AlphaBlendFunction; blendState.BlendFactor = BlendState.AlphaBlend.BlendFactor; blendState.ColorBlendFunction = BlendState.AlphaBlend.ColorBlendFunction; blendState.ColorWriteChannels = BlendState.AlphaBlend.ColorWriteChannels; blendState.ColorWriteChannels1 = BlendState.AlphaBlend.ColorWriteChannels1; blendState.ColorWriteChannels2 = BlendState.AlphaBlend.ColorWriteChannels2; blendState.ColorWriteChannels3 = BlendState.AlphaBlend.ColorWriteChannels3; blendState.MultiSampleMask = BlendState.AlphaBlend.MultiSampleMask; } else { blendState.AlphaBlendFunction = BlendState.NonPremultiplied.AlphaBlendFunction; blendState.BlendFactor = BlendState.NonPremultiplied.BlendFactor; blendState.ColorBlendFunction = BlendState.NonPremultiplied.ColorBlendFunction; blendState.ColorWriteChannels = BlendState.NonPremultiplied.ColorWriteChannels; blendState.ColorWriteChannels1 = BlendState.NonPremultiplied.ColorWriteChannels1; blendState.ColorWriteChannels2 = BlendState.NonPremultiplied.ColorWriteChannels2; blendState.ColorWriteChannels3 = BlendState.NonPremultiplied.ColorWriteChannels3; blendState.MultiSampleMask = BlendState.NonPremultiplied.MultiSampleMask; } switch (slot.Data.BlendMode) { case BlendMode.Additive: blendState = BlendState.Additive; break; case BlendMode.Multiply: blendSrc = BlendXna.GetXNABlend(BlendXna.GL_DST_COLOR); blendDst = BlendXna.GetXNABlend(BlendXna.GL_ONE_MINUS_SRC_ALPHA); blendState.ColorSourceBlend = blendSrc; blendState.AlphaSourceBlend = blendSrc; blendState.ColorDestinationBlend = blendDst; blendState.AlphaDestinationBlend = blendDst; break; case BlendMode.Screen: blendSrc = BlendXna.GetXNABlend(premultipliedAlpha ? BlendXna.GL_ONE : BlendXna.GL_SRC_ALPHA); blendDst = BlendXna.GetXNABlend(BlendXna.GL_ONE_MINUS_SRC_COLOR); blendState.ColorSourceBlend = blendSrc; blendState.AlphaSourceBlend = blendSrc; blendState.ColorDestinationBlend = blendDst; blendState.AlphaDestinationBlend = blendDst; break; default: blendState = defaultBlendState; break; } if (device.BlendState != blendState) { End(); device.BlendState = blendState; } // calculate color float a = skeletonA * slot.A * attachmentColorA; if (premultipliedAlpha) { color = new Color( skeletonR * slot.R * attachmentColorR * a, skeletonG * slot.G * attachmentColorG * a, skeletonB * slot.B * attachmentColorB * a, a); } else { color = new Color( skeletonR * slot.R * attachmentColorR, skeletonG * slot.G * attachmentColorG, skeletonB * slot.B * attachmentColorB, a); } Color darkColor = new Color(); if (slot.HasSecondColor) { if (premultipliedAlpha) { darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a); } else { darkColor = new Color(slot.R2 * a, slot.G2 * a, slot.B2 * a); } } darkColor.A = premultipliedAlpha ? (byte)255 : (byte)0; // clip if (clipper.IsClipping) { clipper.ClipTriangles(vertices, verticesCount << 1, indices, indicesCount, uvs); vertices = clipper.ClippedVertices.Items; verticesCount = clipper.ClippedVertices.Count >> 1; indices = clipper.ClippedTriangles.Items; indicesCount = clipper.ClippedTriangles.Count; uvs = clipper.ClippedUVs.Items; } if (verticesCount == 0 || indicesCount == 0) { continue; } // submit to batch MeshItem item = batcher.NextItem(verticesCount, indicesCount); if (textureObject is Texture2D) { item.texture = (Texture2D)textureObject; } else { item.textureLayers = (Texture2D[])textureObject; item.texture = item.textureLayers[0]; } for (int ii = 0, nn = indicesCount; ii < nn; ii++) { item.triangles[ii] = indices[ii]; } VertexPositionColorTextureColor[] itemVertices = item.vertices; for (int ii = 0, v = 0, nn = verticesCount << 1; v < nn; ii++, v += 2) { itemVertices[ii].Color = color; itemVertices[ii].Color2 = darkColor; itemVertices[ii].Position.X = vertices[v]; itemVertices[ii].Position.Y = vertices[v + 1]; itemVertices[ii].Position.Z = attachmentZOffset; itemVertices[ii].TextureCoordinate.X = uvs[v]; itemVertices[ii].TextureCoordinate.Y = uvs[v + 1]; if (VertexEffect != null) { VertexEffect.Transform(ref itemVertices[ii]); } } clipper.ClipEnd(slot); } clipper.ClipEnd(); if (VertexEffect != null) { VertexEffect.End(); } }