private static void DrawNormalFlare(Vector3D position, ref Data flare, Vector3 L, float distance) { if (flare.Query == null) { return; } flare.Query.Position = position; flare.Query.Size = flare.Desc.QuerySize; flare.Query.FreqMinMs = flare.Desc.QueryFreqMinMs; flare.Query.FreqRndMs = flare.Desc.QueryFreqRndMs; flare.Query.Visible = true; var intensity = flare.Desc.Intensity; var maxDistance = flare.Desc.MaxDistance; float alpha = flare.Query.Result * flare.Query.Result * intensity; const float minFlareRadius = 0.2f; const float maxFlareRadius = 10; float radius = MathHelper.Clamp(flare.Desc.Range * 20, minFlareRadius, maxFlareRadius); float drawingRadius = radius * flare.Desc.Size; if (flare.Desc.Type == Lights.MyGlareTypeEnum.Directional) { float dot = Vector3.Dot(L, flare.DirectionWorld); alpha *= dot; } if (alpha <= MyMathConstants.EPSILON) { return; } if (distance > maxDistance * .5f) { // distance falloff float falloff = (distance - .5f * maxDistance) / (.5f * maxDistance); falloff = (float)Math.Max(0, 1 - falloff); drawingRadius *= falloff; alpha *= falloff; } if (drawingRadius <= float.Epsilon) { return; } var color = flare.Desc.Color; //color.A = 0; var material = MyTransparentMaterials.GetMaterial(flare.Desc.Material.ToString()); MyBillboardsHelper.AddBillboardOriented(flare.Desc.Material.ToString(), color * alpha, position, MyRender11.Environment.Matrices.InvView.Left, MyRender11.Environment.Matrices.InvView.Up, drawingRadius, MyBillboard.BlenType.AdditiveTop); }
internal static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Color color, ref Vector3D origin, float softParticleDistanceScale = 1.0f, string blendMaterial = "Test", float textureBlendRatio = 0, Vector2 uvOffset = new Vector2(), bool near = false, bool lowres = false, float reflectivity = 0) { Debug.Assert(material != null); Debug.Assert(blendMaterial != null); if (string.IsNullOrEmpty(material) || !MyTransparentMaterials.ContainsMaterial(material)) { material = "ErrorMaterial"; color = Vector4.One; } billboard.Material = material; billboard.BlendMaterial = blendMaterial; billboard.BlendTextureRatio = textureBlendRatio; quad.Point0.AssertIsValid(); quad.Point1.AssertIsValid(); quad.Point2.AssertIsValid(); quad.Point3.AssertIsValid(); // Billboard vertexes billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; billboard.UVOffset = uvOffset; billboard.UVSize = Vector2.One; // Distance for sorting // IMPORTANT: Must be calculated before we do color and alpha misting, because we need distance there billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyRender11.Environment.Matrices.CameraPosition, origin); // Color billboard.Color = color; billboard.Reflectivity = reflectivity; billboard.ColorIntensity = 1; billboard.Near = near; billboard.Lowres = lowres; billboard.ParentID = -1; // Alpha depends on distance to camera. Very close bilboards are more transparent, so player won't see billboard errors or rotating billboards var mat = MyTransparentMaterials.GetMaterial(billboard.Material); if (mat.AlphaMistingEnable) { billboard.Color *= MathHelper.Clamp(((float)Math.Sqrt(billboard.DistanceSquared) - mat.AlphaMistingStart) / (mat.AlphaMistingEnd - mat.AlphaMistingStart), 0, 1); } billboard.Color *= mat.Color; billboard.SoftParticleDistanceScale = softParticleDistanceScale; billboard.ContainedBillboards.Clear(); }
protected unsafe sealed override void RecordCommandsInternal(MyRenderableProxy proxy) { if (proxy.Material.Info.GeometryTextureRef.IsUsed) { MyRenderProxy.Fail(String.Format("Ensure all glass materials for model '{0}' are dynamic materials inside Environment.sbc", proxy.Mesh.Info.Name)); return; } MyTransparentMaterial material; if (!MyTransparentMaterials.TryGetMaterial(proxy.Material.Info.Name.String, out material)) { MyRenderProxy.Fail(String.Format("Missing transparent material '{0}'", proxy.Material.Info.Name)); return; } Stats.Draws++; MyRenderUtils.BindShaderBundle(RC, proxy.Shaders); SetProxyConstants(proxy); BindProxyGeometry(proxy, RC); ISrvBindable texture = MyManagers.FileTextures.GetTexture(material.Texture, MyFileTextureEnum.GUI, true); RC.PixelShader.SetSrv(0, texture); StaticGlassConstants glassConstants = new StaticGlassConstants(); var glassCB = MyCommon.GetObjectCB(sizeof(StaticGlassConstants)); RC.PixelShader.SetConstantBuffer(2, glassCB); var mapping = MyMapping.MapDiscard(glassCB); glassConstants.Color = material.Color; glassConstants.Reflective = material.Reflectivity; mapping.WriteAndPosition(ref glassConstants); mapping.Unmap(); var submesh = proxy.DrawSubmesh; if (proxy.InstanceCount == 0) { RC.DrawIndexed(submesh.IndexCount, submesh.StartIndex, submesh.BaseVertex); ++Stats.Instances; Stats.Triangles += submesh.IndexCount / 3; } else { RC.DrawIndexedInstanced(submesh.IndexCount, proxy.InstanceCount, submesh.StartIndex, submesh.BaseVertex, proxy.StartInstance); Stats.Instances += proxy.InstanceCount; Stats.Triangles += proxy.InstanceCount * submesh.IndexCount / 3; } }
static void PreGatherBillboard(MyBillboard billboard) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.NeedSort) { m_sortedCount++; } else { m_unsortedCount++; } }
private static void DrawNormalFlare(Vector3D position, ref MyFlareDesc flare, Vector3 L, float distance) { //if (m_occlusionRatio <= MyMathConstants.EPSILON) // return; var intensity = flare.Intensity; var maxDistance = flare.MaxDistance; //float alpha = m_occlusionRatio * intensity; float alpha = intensity; const float minFlareRadius = 0.2f; const float maxFlareRadius = 10; float radius = MathHelper.Clamp(flare.Range * 20, minFlareRadius, maxFlareRadius); float drawingRadius = radius * flare.Size; if (flare.Type == Lights.MyGlareTypeEnum.Directional) { float dot = Vector3.Dot(L, flare.Direction); alpha *= dot; } if (alpha <= MyMathConstants.EPSILON) { return; } if (distance > maxDistance * .5f) { // distance falloff float falloff = (distance - .5f * maxDistance) / (.5f * maxDistance); falloff = (float)Math.Max(0, 1 - falloff); drawingRadius *= falloff; alpha *= falloff; } if (drawingRadius <= float.Epsilon) { return; } var color = flare.Color; //color.A = 0; var material = MyTransparentMaterials.GetMaterial(flare.Material.ToString()); MyBillboardsHelper.AddBillboardOriented(flare.Material.ToString(), color * alpha, position, MyRender11.Environment.Matrices.InvView.Left, MyRender11.Environment.Matrices.InvView.Up, drawingRadius); }
static void PreGatherBillboard(MyBillboard billboard) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.NeedSort) { m_sortedCount++; } else { m_unsortedCount++; } if (billboard.Window && MyScreenDecals.HasEntityDecals((uint)billboard.ParentID)) { m_windowCount++; } }
static void PreGatherList(List <MyBillboard> list) { for (int i = 0; i < list.Count; i++) { var billboard = list[i]; if (billboard.ContainedBillboards.Count == 0 && billboard.Material != null) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); m_sortedNum += material.NeedSort ? 1 : 0; } for (int j = 0; j < billboard.ContainedBillboards.Count; j++) { var material = MyTransparentMaterials.GetMaterial(billboard.ContainedBillboards[j].Material); m_sortedNum += material.NeedSort ? 1 : 0; } } }
static void GatherList(List <MyBillboard> list) { for (int i = 0; i < list.Count; i++) { var billboard = list[i]; if (billboard.ContainedBillboards.Count == 0 && billboard.Material != null) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.Reflectivity > 0) { } if (material.NeedSort) { m_sortBuffer[m_sorted++] = billboard; } else { m_sortBuffer[m_sortedNum + m_unsorted++] = billboard; } } for (int j = 0; j < billboard.ContainedBillboards.Count; j++) { if (billboard.ContainedBillboards[j].Material != null) { var material = MyTransparentMaterials.GetMaterial(billboard.ContainedBillboards[j].Material); if (material.NeedSort) { m_sortBuffer[m_sorted++] = billboard.ContainedBillboards[j]; } else { m_sortBuffer[m_sortedNum + m_unsorted++] = billboard.ContainedBillboards[j]; } } } } }
static void GatherList(List <MyBillboard> list, ref int sortedIndex, ref int unsortedIndex) { for (int i = 0; i < list.Count; i++) { var billboard = list[i]; if (billboard.ContainedBillboards.Count == 0 && billboard.Material != null) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.NeedSort) { m_sortedBuffer[sortedIndex++] = billboard; } else { m_sortedBuffer[m_sortedCount + unsortedIndex++] = billboard; } } for (int j = 0; j < billboard.ContainedBillboards.Count; j++) { if (billboard.ContainedBillboards[j].Material != null) { var material = MyTransparentMaterials.GetMaterial(billboard.ContainedBillboards[j].Material); if (material.NeedSort) { m_sortedBuffer[sortedIndex++] = billboard.ContainedBillboards[j]; } else { m_sortedBuffer[m_sortedCount + unsortedIndex++] = billboard.ContainedBillboards[j]; } } } } }
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_atlasedTextures[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; if (material.UseAtlas) { var atlasItem = m_atlasedTextures[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.UVOffset.X, material.UVOffset.Y + billboard.UVOffset.Y); var uv2 = new Vector2(material.UVOffset.X + material.UVSize.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y); var uv3 = new Vector2(material.UVOffset.X + billboard.UVOffset.X, material.UVOffset.Y + material.UVSize.Y + billboard.UVOffset.Y); if (material.UseAtlas) { var atlasItem = m_atlasedTextures[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; 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; m_batches.Add(batch); } }
public override void DeserializeValue(XmlReader reader, out object value) { base.DeserializeValue(reader, out value); value = MyTransparentMaterials.GetMaterial((string)value); }
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++; } }