static bool GatherInternal(Func <MyBillboard, bool> handleWindow) { m_batches.Clear(); // counting sorted billboards m_sortedCount = 0; m_unsortedCount = 0; m_windowCount = 0; PreGatherList(MyRenderProxy.BillboardsRead); PreGatherList(m_billboardsOnce); if (BillboardCount == 0) { return(false); } ResizeStorage(); int sortedIndex = 0; int unsortedIndex = 0; GatherList(MyRenderProxy.BillboardsRead, ref sortedIndex, ref unsortedIndex); GatherList(m_billboardsOnce, ref sortedIndex, ref unsortedIndex); Array.Sort(m_sortedBuffer, 0, m_sortedCount); int i = 0; bool resetBindings = false; int windowidx = 0; var N = BillboardCountSafe; int currentOffset = 0; ISrvBindable prevTex = null; ISrvBindable batchTex = null; MyTransparentMaterial prevMaterial = null; while (true) { if (i == N) { AddBatch(N, currentOffset, prevTex, prevMaterial); break; } MyBillboard billboard = m_sortedBuffer[i]; MyTransparentMaterial material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); batchTex = atlasItem.Texture; } else { MyFileTextureManager texManager = MyManagers.FileTextures; switch (material.TextureType) { case MyTransparentMaterialTextureType.FileTexture: batchTex = texManager.GetTexture(material.Texture, MyFileTextureEnum.GUI, true); break; case MyTransparentMaterialTextureType.RenderTarget: batchTex = MyRender11.DrawSpritesOffscreen(material.Name, material.TargetSize.X, material.TargetSize.Y); resetBindings = true; break; default: throw new Exception(); } } bool closeBatch = i > 0 && (batchTex != prevTex || i == m_sortedCount); if (closeBatch) { AddBatch(i, currentOffset, prevTex, prevMaterial); currentOffset = i; } var billboardData = new MyBillboardData(); var billboardVertices = new MyBillboardVertexData(); billboardData.CustomProjectionID = billboard.CustomViewProjection; billboardData.Color = billboard.Color; billboardData.Color.X *= billboard.ColorIntensity; billboardData.Color.Y *= billboard.ColorIntensity; billboardData.Color.Z *= billboard.ColorIntensity; billboardData.AlphaCutout = billboard.AlphaCutout; billboardData.AlphaSaturation = material.AlphaSaturation; billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale; billboardData.Reflective = billboard.Reflectivity; Vector3D pos0 = billboard.Position0; Vector3D pos1 = billboard.Position1; Vector3D pos2 = billboard.Position2; Vector3D pos3 = billboard.Position3; if (billboard.ParentID != -1) { if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null) { var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix; Vector3D.Transform(ref pos0, ref matrix, out pos0); Vector3D.Transform(ref pos1, ref matrix, out pos1); Vector3D.Transform(ref pos2, ref matrix, out pos2); Vector3D.Transform(ref pos3, ref matrix, out pos3); } } MyEnvironmentMatrices envMatrices = MyRender11.Environment.Matrices; if (MyStereoRender.Enable) { if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT) { envMatrices = MyStereoRender.EnvMatricesLeftEye; } else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT) { envMatrices = MyStereoRender.EnvMatricesRightEye; } } if (billboard.CustomViewProjection != -1) { var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection]; //pos0 -= envMatrices.CameraPosition; //pos1 -= envMatrices.CameraPosition; //pos2 -= envMatrices.CameraPosition; //pos3 -= envMatrices.CameraPosition; } else { pos0 -= envMatrices.CameraPosition; pos1 -= envMatrices.CameraPosition; pos2 -= envMatrices.CameraPosition; pos3 -= envMatrices.CameraPosition; } var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); billboardData.Normal = normal; billboardVertices.V0.Position = pos0; billboardVertices.V1.Position = pos1; billboardVertices.V2.Position = pos2; billboardVertices.V3.Position = pos3; var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); } billboardVertices.V0.Texcoord = new HalfVector2(uv0); billboardVertices.V1.Texcoord = new HalfVector2(uv1); billboardVertices.V2.Texcoord = new HalfVector2(uv2); billboardVertices.V3.Texcoord = new HalfVector2(uv3); pos0.AssertIsValid(); pos1.AssertIsValid(); pos2.AssertIsValid(); pos3.AssertIsValid(); MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard; if (triBillboard != null) { billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0); billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1); billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2); billboardData.Normal = triBillboard.Normal0; } m_arrayDataBillboards.Data[i] = billboardData; m_arrayDataBillboards.Vertex[i] = billboardVertices; if (billboard.Window && handleWindow(billboard)) { m_sorteWindowIndices[windowidx] = i; windowidx++; } prevTex = batchTex; prevMaterial = material; i++; } // Sort windows data from closer to farest int windowCount = WindowCountSafe; Array.Sort(m_sorteWindowIndices, 0, windowCount, BillboardComparer); for (int it = 0; it < windowCount; it++) { m_arrayDataWindows.Data[it] = m_arrayDataBillboards.Data[m_sorteWindowIndices[it]]; m_arrayDataWindows.Vertex[it] = m_arrayDataBillboards.Vertex[m_sorteWindowIndices[it]]; } return(resetBindings); }
static void Gather() { // counting sorted billboards m_batches.Clear(); m_sortedNum = 0; PreGatherList(MyRenderProxy.BillboardsRead); PreGatherList(m_billboardsOnce); m_sortedBillboardsNum = m_sortedNum; m_unsorted = 0; m_sorted = 0; GatherList(MyRenderProxy.BillboardsRead); GatherList(m_billboardsOnce); Array.Sort(m_sortBuffer, 0, m_sortedNum); //Array.Reverse(m_sortBuffer, 0, m_sortedNum); //Array.Sort(m_sortBuffer, m_sortedNum, m_unsorted); var N = m_sorted + m_unsorted; var batch = new MyBillboardBatch(); //MyAssetTexture prevTexture = null; var prevTexId = TexId.NULL; int currentOffset = 0; if (N > 0) { var material = MyTransparentMaterials.GetMaterial(m_sortBuffer[0].Material); if (material.UseAtlas) { var item = m_atlas.FindElement(material.Texture); prevTexId = item.TextureId; } else { PreloadTexture(material.Texture); //prevTexture = MyTextureManager.GetTextureFast(material.Texture); prevTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true); } } TexId batchTexId = TexId.NULL; MyTransparentMaterial prevMaterial = null; for (int i = 0; i < N; i++) { var billboard = m_sortBuffer[i]; var material = MyTransparentMaterials.GetMaterial(billboard.Material); var billboardData = new MyBillboardData(); billboardData.CustomProjectionID = billboard.CustomViewProjection; billboardData.Color = billboard.Color; billboardData.Color *= billboard.ColorIntensity; billboardData.AlphaCutout = billboard.AlphaCutout; billboardData.AlphaSaturation = material.AlphaSaturation; billboardData.SoftParticleDistanceScale = material.SoftParticleDistanceScale; if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); //billboardData.UvModifiers = new HalfVector4(atlasItem.UvOffsetScale); batchTexId = atlasItem.TextureId; } else { batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true); } billboardData.Reflective = billboard.Reflectivity; Vector3D pos0 = billboard.Position0; Vector3D pos1 = billboard.Position1; Vector3D pos2 = billboard.Position2; Vector3D pos3 = billboard.Position3; if (billboard.ParentID != -1) { if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null) { var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix; Vector3D.Transform(ref pos0, ref matrix, out pos0); Vector3D.Transform(ref pos1, ref matrix, out pos1); Vector3D.Transform(ref pos2, ref matrix, out pos2); Vector3D.Transform(ref pos3, ref matrix, out pos3); } } if (billboard.CustomViewProjection != -1) { var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection]; //pos0 -= MyEnvironment.CameraPosition; //pos1 -= MyEnvironment.CameraPosition; //pos2 -= MyEnvironment.CameraPosition; //pos3 -= MyEnvironment.CameraPosition; } else { pos0 -= MyEnvironment.CameraPosition; pos1 -= MyEnvironment.CameraPosition; pos2 -= MyEnvironment.CameraPosition; pos3 -= MyEnvironment.CameraPosition; } var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); billboardData.Normal = normal; m_vertexData[i * 4 + 0].Position = pos0; m_vertexData[i * 4 + 1].Position = pos1; m_vertexData[i * 4 + 2].Position = pos2; m_vertexData[i * 4 + 3].Position = pos3; var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); } m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(uv0); m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(uv1); m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(uv2); m_vertexData[i * 4 + 3].Texcoord = new HalfVector2(uv3); pos0.AssertIsValid(); pos1.AssertIsValid(); pos2.AssertIsValid(); pos3.AssertIsValid(); MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard; if (triBillboard != null) { m_vertexData[i * 4 + 3].Position = pos2; // second triangle will die in rasterizer m_vertexData[i * 4 + 0].Texcoord = new HalfVector2(triBillboard.UV0); m_vertexData[i * 4 + 1].Texcoord = new HalfVector2(triBillboard.UV1); m_vertexData[i * 4 + 2].Texcoord = new HalfVector2(triBillboard.UV2); billboardData.Normal = triBillboard.Normal0; // pew pew pew :O } m_billboardData[i] = billboardData; bool closeBatch = (batchTexId != prevTexId) || ((i == m_sortedNum) && (i > 0)); if (closeBatch) { batch = new MyBillboardBatch(); batch.Offset = currentOffset; batch.Num = i - currentOffset; batch.Texture = prevTexId != TexId.NULL ? MyTextures.Views[prevTexId.Index] : null; batch.Lit = prevMaterial.CanBeAffectedByOtherLights; batch.AlphaCutout = prevMaterial.AlphaCutout; m_batches.Add(batch); currentOffset = i; } prevTexId = batchTexId; prevMaterial = material; } if (N > 0) { batch = new MyBillboardBatch(); batch.Offset = currentOffset; batch.Num = N - currentOffset; batch.Texture = prevTexId != TexId.NULL ? MyTextures.GetView(prevTexId) : null; batch.Lit = prevMaterial.CanBeAffectedByOtherLights; batch.AlphaCutout = prevMaterial.AlphaCutout; m_batches.Add(batch); } }
static bool GatherInternal() { m_batches.Clear(); // counting sorted billboards ClearBucketCounts(); PreGatherList(MyRenderProxy.BillboardsRead); PreGatherList(m_billboardsOnce); int billboardCount = 0; for (int j = 0; j < BUCKETS_COUNT; j++) { billboardCount += m_bucketCounts[j]; } if (billboardCount == 0) { return(false); } m_billboardCountSafe = billboardCount > MAX_BILLBOARDS_SIZE ? MAX_BILLBOARDS_SIZE : billboardCount; InitGatherList(billboardCount, m_billboardCountSafe); InitBucketIndices(); GatherList(MyRenderProxy.BillboardsRead); GatherList(m_billboardsOnce); InitBucketIndices(); int i; for (i = 0; i < BUCKETS_COUNT; i++) { Array.Sort(m_tempBuffer, m_bucketIndices[i], m_bucketCounts[i]); } bool resetBindings = false; int currentOffset = 0; ISrvBindable prevTex = null; MyTransparentMaterial prevMaterial = null; for (i = 0; i < m_billboardCountSafe; i++) { MyBillboard billboard = m_tempBuffer[i]; MyTransparentMaterial material = MyTransparentMaterials.GetMaterial(billboard.Material); ISrvBindable batchTex = null; if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); batchTex = atlasItem.Texture; } else { MyFileTextureManager texManager = MyManagers.FileTextures; switch (material.TextureType) { case MyTransparentMaterialTextureType.FileTexture: if (material.Texture == null || !m_fileTextures.TryGetValue(material.Texture, out batchTex)) { batchTex = texManager.GetTexture(material.Texture, MyFileTextureEnum.GUI, true); if (material.Texture != null) { m_fileTextures.Add(material.Texture, batchTex); } else { MyRenderProxy.Fail("Material: " + material.Name + " is missing a texture."); } } break; case MyTransparentMaterialTextureType.RenderTarget: batchTex = MyRender11.DrawSpritesOffscreen(material.Name, material.TargetSize.X, material.TargetSize.Y); resetBindings = true; break; default: throw new Exception(); } } bool boundary = IsBucketBoundary(i); bool closeBatch = i > 0 && (batchTex != prevTex || boundary); if (closeBatch) { AddBatch(i, currentOffset, prevTex, prevMaterial); currentOffset = i; } var billboardData = new MyBillboardData(); var billboardVertices = new MyBillboardVertexData(); billboardData.CustomProjectionID = billboard.CustomViewProjection; billboardData.Color = billboard.Color; billboardData.Color.X *= billboard.ColorIntensity; billboardData.Color.Y *= billboard.ColorIntensity; billboardData.Color.Z *= billboard.ColorIntensity; billboardData.AlphaCutout = billboard.AlphaCutout; billboardData.AlphaSaturation = material.AlphaSaturation; billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale; billboardData.Reflective = billboard.Reflectivity; Vector3D pos0 = billboard.Position0; Vector3D pos1 = billboard.Position1; Vector3D pos2 = billboard.Position2; Vector3D pos3 = billboard.Position3; if (billboard.ParentID != -1) { var parent = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID); if (parent != null) { var matrix = parent.WorldMatrix; Vector3D.Transform(ref pos0, ref matrix, out pos0); Vector3D.Transform(ref pos1, ref matrix, out pos1); Vector3D.Transform(ref pos2, ref matrix, out pos2); Vector3D.Transform(ref pos3, ref matrix, out pos3); } } MyEnvironmentMatrices envMatrices = MyRender11.Environment.Matrices; if (MyStereoRender.Enable) { if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT) { envMatrices = MyStereoRender.EnvMatricesLeftEye; } else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT) { envMatrices = MyStereoRender.EnvMatricesRightEye; } } if (billboard.CustomViewProjection == -1) { pos0 -= envMatrices.CameraPosition; pos1 -= envMatrices.CameraPosition; pos2 -= envMatrices.CameraPosition; pos3 -= envMatrices.CameraPosition; } var normal = Vector3D.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); billboardData.Normal = normal; billboardVertices.V0.Position = pos0; billboardVertices.V1.Position = pos1; billboardVertices.V2.Position = pos2; billboardVertices.V3.Position = pos3; var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); } billboardVertices.V0.Texcoord = new HalfVector2(uv0); billboardVertices.V1.Texcoord = new HalfVector2(uv1); billboardVertices.V2.Texcoord = new HalfVector2(uv2); billboardVertices.V3.Texcoord = new HalfVector2(uv3); pos0.AssertIsValid(); pos1.AssertIsValid(); pos2.AssertIsValid(); pos3.AssertIsValid(); MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard; if (triBillboard != null) { billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0); billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1); billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2); billboardData.Normal = triBillboard.Normal0; } m_arrayDataBillboards.Data[i] = billboardData; m_arrayDataBillboards.Vertex[i] = billboardVertices; prevTex = batchTex; prevMaterial = material; } AddBatch(m_billboardCountSafe, currentOffset, prevTex, prevMaterial); TransferDataCustomProjections(); TransferDataBillboards(0, m_billboardCountSafe, ref m_arrayDataBillboards); return(resetBindings); }
static void Gather() { m_batches.Clear(); // counting sorted billboards m_sortedCount = 0; m_unsortedCount = 0; m_windowCount = 0; PreGatherList(MyRenderProxy.BillboardsRead); PreGatherList(m_billboardsOnce); if (BillboardCount == 0) { return; } ResizeStorage(); int sortedIndex = 0; int unsortedIndex = 0; GatherList(MyRenderProxy.BillboardsRead, ref sortedIndex, ref unsortedIndex); GatherList(m_billboardsOnce, ref sortedIndex, ref unsortedIndex); Array.Sort(m_sortedBuffer, 0, m_sortedCount); int i = 0; int windowidx = 0; var N = BillboardCountSafe; int currentOffset = 0; TexId prevTexId = TexId.NULL; TexId batchTexId = TexId.NULL; MyTransparentMaterial prevMaterial = null; while (true) { if (i == N) { AddBatch(N, currentOffset, prevTexId, prevMaterial); break; } MyBillboard billboard = m_sortedBuffer[i]; MyTransparentMaterial material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); batchTexId = atlasItem.TextureId; } else { batchTexId = MyTextures.GetTexture(material.Texture, MyTextureEnum.GUI, true); } bool closeBatch = i > 0 && (batchTexId != prevTexId || i == m_sortedCount); if (closeBatch) { AddBatch(i, currentOffset, prevTexId, prevMaterial); currentOffset = i; } var billboardData = new MyBillboardData(); var billboardVertices = new MyBillboardVertexData(); billboardData.CustomProjectionID = billboard.CustomViewProjection; billboardData.Color = billboard.Color; billboardData.Color.X *= billboard.ColorIntensity; billboardData.Color.Y *= billboard.ColorIntensity; billboardData.Color.Z *= billboard.ColorIntensity; billboardData.AlphaCutout = billboard.AlphaCutout; billboardData.AlphaSaturation = material.AlphaSaturation; billboardData.SoftParticleDistanceScale = billboard.SoftParticleDistanceScale * material.SoftParticleDistanceScale; billboardData.Reflective = billboard.Reflectivity; Vector3D pos0 = billboard.Position0; Vector3D pos1 = billboard.Position1; Vector3D pos2 = billboard.Position2; Vector3D pos3 = billboard.Position3; if (billboard.ParentID != -1) { if (MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID) != null) { var matrix = MyIDTracker <MyActor> .FindByID((uint)billboard.ParentID).WorldMatrix; Vector3D.Transform(ref pos0, ref matrix, out pos0); Vector3D.Transform(ref pos1, ref matrix, out pos1); Vector3D.Transform(ref pos2, ref matrix, out pos2); Vector3D.Transform(ref pos3, ref matrix, out pos3); } } MyEnvironmentMatrices envMatrices = MyRender11.Environment; if (MyStereoRender.Enable) { if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT) { envMatrices = MyStereoRender.EnvMatricesLeftEye; } else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT) { envMatrices = MyStereoRender.EnvMatricesRightEye; } } if (billboard.CustomViewProjection != -1) { var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection]; //pos0 -= envMatrices.CameraPosition; //pos1 -= envMatrices.CameraPosition; //pos2 -= envMatrices.CameraPosition; //pos3 -= envMatrices.CameraPosition; } else { pos0 -= envMatrices.CameraPosition; pos1 -= envMatrices.CameraPosition; pos2 -= envMatrices.CameraPosition; pos3 -= envMatrices.CameraPosition; } var normal = Vector3.Cross(pos1 - pos0, pos2 - pos0); normal.Normalize(); billboardData.Normal = normal; billboardVertices.V0.Position = pos0; billboardVertices.V1.Position = pos1; billboardVertices.V2.Position = pos2; billboardVertices.V3.Position = pos3; var uv0 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv1 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X * billboard.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y + material.UVSize.Y * billboard.UVSize.Y); if (material.UseAtlas) { var atlasItem = m_atlas.FindElement(material.Texture); uv0 = uv0 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv1 = uv1 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv2 = uv2 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); uv3 = uv3 * new Vector2(atlasItem.UvOffsetScale.Z, atlasItem.UvOffsetScale.W) + new Vector2(atlasItem.UvOffsetScale.X, atlasItem.UvOffsetScale.Y); } billboardVertices.V0.Texcoord = new HalfVector2(uv0); billboardVertices.V1.Texcoord = new HalfVector2(uv1); billboardVertices.V2.Texcoord = new HalfVector2(uv2); billboardVertices.V3.Texcoord = new HalfVector2(uv3); pos0.AssertIsValid(); pos1.AssertIsValid(); pos2.AssertIsValid(); pos3.AssertIsValid(); MyTriangleBillboard triBillboard = billboard as MyTriangleBillboard; if (triBillboard != null) { billboardVertices.V3.Position = pos2; // second triangle will die in rasterizer billboardVertices.V0.Texcoord = new HalfVector2(triBillboard.UV0); billboardVertices.V1.Texcoord = new HalfVector2(triBillboard.UV1); billboardVertices.V2.Texcoord = new HalfVector2(triBillboard.UV2); billboardData.Normal = triBillboard.Normal0; } m_arrayDataBillboards.Data[i] = billboardData; m_arrayDataBillboards.Vertex[i] = billboardVertices; if (billboard.Window && MyScreenDecals.HasEntityDecals((uint)billboard.ParentID)) { m_arrayDataWindows.Data[windowidx] = billboardData; m_arrayDataWindows.Vertex[windowidx] = billboardVertices; windowidx++; } prevTexId = batchTexId; prevMaterial = material; i++; } }