public static bool AddQuad(string material, ref MyQuadD quad, ref Color color, ref Vector3D vctPos, int priority = 0, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return(false); } MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return(false); } billboard.Priority = priority; CreateBillboard(billboard, ref quad, material, ref color, ref vctPos, false, false, false, customViewProjection); VRageRender.MyRenderProxy.AddBillboard(billboard); return(true); }
private static void GetBillboardQuadRotated(VRageRender.MyBillboard billboard, ref Vector3D position, Vector2 radius, ref Matrix transform, Vector3 left, Vector3 up) { // Two main vectors of a billboard rotated around the view axis/vector Vector3 billboardAxisX = new Vector3(); billboardAxisX.X = radius.X * left.X; billboardAxisX.Y = radius.X * left.Y; billboardAxisX.Z = radius.X * left.Z; Vector3 billboardAxisY = new Vector3(); billboardAxisY.X = radius.Y * up.X; billboardAxisY.Y = radius.Y * up.Y; billboardAxisY.Z = radius.Y * up.Z; Vector3D v1 = Vector3.TransformNormal(billboardAxisX + billboardAxisY, transform); Vector3D v2 = Vector3.TransformNormal(billboardAxisX - billboardAxisY, transform); // Coordinates of four points of a billboard's quad billboard.Position0.X = position.X + v1.X; billboard.Position0.Y = position.Y + v1.Y; billboard.Position0.Z = position.Z + v1.Z; billboard.Position1.X = position.X - v2.X; billboard.Position1.Y = position.Y - v2.Y; billboard.Position1.Z = position.Z - v2.Z; billboard.Position2.X = position.X - v1.X; billboard.Position2.Y = position.Y - v1.Y; billboard.Position2.Z = position.Z - v1.Z; billboard.Position3.X = position.X + v2.X; billboard.Position3.Y = position.Y + v2.Y; billboard.Position3.Z = position.Z + v2.Z; }
public void PrepareForDraw() { //if (WasVisibleLastFrame != LastFrameVisibilityEnum.NotVisibleLastFrame) // if (RenderCounter == 0 || ((MyRender.RenderCounter - RenderCounter) < FRAMES_TO_SKIP)) //more than FRAMES_TO_SKIP frames consider effect as invisible { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Sort generations"); m_sortedGenerations.Clear(); foreach (IMyParticleGeneration generation in m_generations) { m_sortedGenerations.Add(generation); } m_sortedGenerations.Sort(); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); VRageRender.MyBillboard effectBillboard = null; VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("PrepareForDraw generations"); foreach (IMyParticleGeneration generation in m_sortedGenerations) { generation.PrepareForDraw(ref effectBillboard); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } }
internal static void AddBillboardOriented(string material, Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, float softParticleDistanceScale = 1.0f, int customViewProjection = -1) { if (!MyRender11.DebugOverrides.BillboardsDynamic) { return; } Debug.Assert(material != null); origin.AssertIsValid(); leftVector.AssertIsValid(); upVector.AssertIsValid(); radius.AssertIsValid(); MyDebug.AssertDebug(radius > 0); MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce(); if (billboard == null) { return; } billboard.Priority = priority; billboard.CustomViewProjection = customViewProjection; MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin, softParticleDistanceScale); }
// Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc). // This billboard isn't facing the camera. It's always oriented in specified direction. May be used as thrusts, or inner light of reflector. // It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare). public static void AddBillboardOriented(string material, Vector4 color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int customViewProjection = -1, float reflection = 0) { Debug.Assert(material != null); if (!IsEnabled) { return; } MyUtils.AssertIsValid(origin); MyUtils.AssertIsValid(leftVector); MyUtils.AssertIsValid(upVector); MyUtils.AssertIsValid(radius); MyDebug.AssertDebug(radius > 0); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard();// m_preallocatedBillboards.Allocate(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin, customViewProjection, reflection); billboard.BlendType = MyBillboard.BlenType.Standard; VRageRender.MyRenderProxy.AddBillboard(billboard); }
internal static void AddBillboardOriented(string material, Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float radius, int priority = 0, int customViewProjection = -1) { Debug.Assert(material != null); origin.AssertIsValid(); leftVector.AssertIsValid(); upVector.AssertIsValid(); radius.AssertIsValid(); MyDebug.AssertDebug(radius > 0); MyBillboard billboard = SpawnBillboard(); if (billboard == null) { return; } billboard.Priority = priority; billboard.CustomViewProjection = customViewProjection; MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, radius, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin); }
public void PrepareForDraw() { if (m_needSorting) { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Sort generations"); m_sortedGenerations.Clear(); foreach (IMyParticleGeneration generation in m_generations) { m_sortedGenerations.Add(generation); } m_sortedGenerations.Sort(); m_drawGenerations = m_sortedGenerations; VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } else { m_drawGenerations = m_generations; } VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("PrepareForDraw generations"); VRageRender.MyBillboard effectBillboard = null; foreach (IMyParticleGeneration generation in m_drawGenerations) { generation.PrepareForDraw(ref effectBillboard); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); }
public static void AddBillboardOriented(string material, Vector4 color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float width, float height, Vector2 uvOffset, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return; } VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, width, height, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin, uvOffset, customViewProjection); billboard.BlendType = MyBillboard.BlenType.Standard; VRageRender.MyRenderProxy.AddBillboard(billboard); }
public static void AddBillboardOriented(string material, Color color, Vector3D origin, Vector3 leftVector, Vector3 upVector, float width, float height, Vector2 uvOffset, int priority = 0, bool colorize = false, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return; } //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } billboard.Priority = priority; MyQuadD quad; MyUtils.GetBillboardQuadOriented(out quad, ref origin, width, height, ref leftVector, ref upVector); CreateBillboard(billboard, ref quad, material, ref color, ref origin, uvOffset, colorize, false, false, customViewProjection); VRageRender.MyRenderProxy.AddBillboard(billboard); }
internal static void AddPointBillboard(string material, Color color, Vector3D origin, float radius, float angle, int priority = 0, int customViewProjection = -1) { if (!MyRender11.DebugOverrides.BillboardsDynamic) { return; } Debug.Assert(material != null); origin.AssertIsValid(); angle.AssertIsValid(); MyQuadD quad; if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, angle, MyRender11.Environment.Matrices.CameraPosition) != false) { MyBillboard billboard = MyBillboardRenderer.AddBillboardOnce(); if (billboard == null) { return; } billboard.Priority = priority; billboard.CustomViewProjection = customViewProjection; CreateBillboard(billboard, ref quad, material, ref color, ref origin); } }
/// <summary> /// Return quad whos face is always looking to the camera. /// IMPORTANT: This bilboard looks same as point vertexes (point sprites) - horizontal and vertical axes of billboard are always parallel to screen /// That means, if billboard is in the left-up corner of screen, it won't be distorted by perspective. If will look as 2D quad on screen. As I said, it's same as GPU points. /// </summary> private static void GetBillboardQuadRotated(VRageRender.MyBillboard billboard, ref Vector3D position, float radius, float angle) { float angleCos = radius * (float)Math.Cos(angle); float angleSin = radius * (float)Math.Sin(angle); // Two main vectors of a billboard rotated around the view axis/vector Vector3D billboardAxisX = new Vector3D(); billboardAxisX.X = angleCos * MyTransparentGeometry.Camera.Left.X + angleSin * MyTransparentGeometry.Camera.Up.X; billboardAxisX.Y = angleCos * MyTransparentGeometry.Camera.Left.Y + angleSin * MyTransparentGeometry.Camera.Up.Y; billboardAxisX.Z = angleCos * MyTransparentGeometry.Camera.Left.Z + angleSin * MyTransparentGeometry.Camera.Up.Z; Vector3D billboardAxisY = new Vector3D(); billboardAxisY.X = -angleSin * MyTransparentGeometry.Camera.Left.X + angleCos * MyTransparentGeometry.Camera.Up.X; billboardAxisY.Y = -angleSin * MyTransparentGeometry.Camera.Left.Y + angleCos * MyTransparentGeometry.Camera.Up.Y; billboardAxisY.Z = -angleSin * MyTransparentGeometry.Camera.Left.Z + angleCos * MyTransparentGeometry.Camera.Up.Z; // Coordinates of four points of a billboard's quad billboard.Position0.X = position.X + billboardAxisX.X + billboardAxisY.X; billboard.Position0.Y = position.Y + billboardAxisX.Y + billboardAxisY.Y; billboard.Position0.Z = position.Z + billboardAxisX.Z + billboardAxisY.Z; billboard.Position1.X = position.X - billboardAxisX.X + billboardAxisY.X; billboard.Position1.Y = position.Y - billboardAxisX.Y + billboardAxisY.Y; billboard.Position1.Z = position.Z - billboardAxisX.Z + billboardAxisY.Z; billboard.Position2.X = position.X - billboardAxisX.X - billboardAxisY.X; billboard.Position2.Y = position.Y - billboardAxisX.Y - billboardAxisY.Y; billboard.Position2.Z = position.Z - billboardAxisX.Z - billboardAxisY.Z; billboard.Position3.X = position.X + billboardAxisX.X - billboardAxisY.X; billboard.Position3.Y = position.Y + billboardAxisX.Y - billboardAxisY.Y; billboard.Position3.Z = position.Z + billboardAxisX.Z - billboardAxisY.Z; }
public static bool AddAttachedQuad(string material, ref MyQuadD quad, Vector4 color, ref Vector3D vctPos, int renderObjectID) { Debug.Assert(material != null); if (!IsEnabled) { return(false); } MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return(false); } CreateBillboard(billboard, ref quad, material, ref color, ref vctPos); billboard.ParentID = renderObjectID; billboard.BlendType = MyBillboard.BlenType.Standard; VRageRender.MyRenderProxy.AddBillboard(billboard); return(true); }
public static VRageRender.MyBillboard AddBillboardParticle(MyAnimatedParticle particle, VRageRender.MyBillboard effectBillboard, bool sort) { //MyBillboard billboard = m_preallocatedParticleBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard != null) { MyTransparentGeometry.StartParticleProfilingBlock("item.Value.Draw"); if (particle.Draw(billboard) == true) { if (!sort) { effectBillboard.ContainedBillboards.Add(billboard); } MyPerformanceCounter.PerCameraDrawWrite.NewParticlesCount++; } billboard.CustomViewProjection = -1; MyTransparentGeometry.EndParticleProfilingBlock(); } return(billboard); }
public static void AddLineBillboard(string material, Color color, Vector3D origin, int renderObjectID, ref MatrixD worldToLocal, Vector3 directionNormalized, float length, float thickness, int priority = 0, bool near = false, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return; } MyDebug.AssertIsValid(origin); MyDebug.AssertIsValid(length); MyDebug.AssertDebug(length > 0); MyDebug.AssertDebug(thickness > 0); //VRageRender.MyBillboard billboard = m_preallocatedBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } billboard.Priority = priority; billboard.UVOffset = Vector2.Zero; billboard.UVSize = Vector2.One; MyPolyLineD polyLine; polyLine.LineDirectionNormalized = directionNormalized; polyLine.Point0 = origin; polyLine.Point1 = origin + directionNormalized * length; polyLine.Thickness = thickness; MyQuadD quad; Vector3D cameraPosition = customViewProjection == -1 ? MyTransparentGeometry.Camera.Translation : VRageRender.MyRenderProxy.BillboardsViewProjectionWrite[customViewProjection].CameraPosition; MyUtils.GetPolyLineQuad(out quad, ref polyLine, cameraPosition); CreateBillboard(billboard, ref quad, material, ref color, ref origin, false, near, false, customViewProjection); if (renderObjectID != -1) { Vector3D.Transform(ref billboard.Position0, ref worldToLocal, out billboard.Position0); Vector3D.Transform(ref billboard.Position1, ref worldToLocal, out billboard.Position1); Vector3D.Transform(ref billboard.Position2, ref worldToLocal, out billboard.Position2); Vector3D.Transform(ref billboard.Position3, ref worldToLocal, out billboard.Position3); billboard.ParentID = renderObjectID; } billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); VRageRender.MyRenderProxy.AddBillboard(billboard); }
/// <summary>Render depth and normals of windows to the specified target</summary> /// <returns>True if windows to be rendered found</returns> /// <param name="squaredDistanceMin">Squared distance internal minor</param> internal static bool RenderWindowsDepthOnly(IDepthStencil depthStencil, IRtvBindable gbuffer1, float squaredDistanceMin, float squaredDistanceMax) { int offset = 0; int windowsCount = 0; int windowsCountMax = WindowCountSafe; for (int it = 0; it < windowsCountMax; it++) { // Interval is [min, max) MyBillboard billboard = m_sortedBuffer[m_sorteWindowIndices[it]]; if (billboard.DistanceSquared >= squaredDistanceMax) { break; } if (billboard.DistanceSquared < squaredDistanceMin) { offset++; } else { windowsCount++; } } if (windowsCount == 0) { return(false); } TransferDataBillboards(offset, windowsCount, ref m_arrayDataWindows); RC.SetRtv(depthStencil, MyDepthStencilAccess.ReadWrite, gbuffer1); BindResourcesCommon(); RC.SetBlendState(null); RC.VertexShader.Set(m_vsDepthOnly); RC.PixelShader.Set(m_psDepthOnly); if (!MyStereoRender.Enable) { RC.DrawIndexed(m_windowCount * 6, 0, 0); } else { MyStereoRender.DrawIndexedBillboards(RC, m_windowCount * 6, 0, 0); } MyStatsUpdater.Passes.DrawBillboards++; RC.SetRasterizerState(null); return(true); }
/// <returns>True if window has decals and is not too far</returns> static bool HandleWindow(MyBillboard billboard) { uint parentID = (uint)billboard.ParentID; if (MyScreenDecals.HasEntityDecals(parentID) && billboard.DistanceSquared < MyScreenDecals.VISIBLE_DECALS_SQ_TH) { m_windowsWithDecals.Add(parentID); return(true); } return(false); }
// This method is like a constructor (which we can't use because billboards are allocated from a pool). // It starts/initializes a billboard. Refs used only for optimalization public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Vector4 color, ref Vector3D origin, Vector2 uvOffset, int customViewProjection = -1, float reflectivity = 0) { System.Diagnostics.Debug.Assert(material != null); if (string.IsNullOrEmpty(material) || !MyTransparentMaterials.ContainsMaterial(material)) { material = "ErrorMaterial"; color = Vector4.One; } billboard.Material = material; MyUtils.AssertIsValid(quad.Point0); MyUtils.AssertIsValid(quad.Point1); MyUtils.AssertIsValid(quad.Point2); MyUtils.AssertIsValid(quad.Point3); // Billboard vertices 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 Vector3D cameraPosition = customViewProjection == -1 ? MyTransparentGeometry.Camera.Translation : VRageRender.MyRenderProxy.BillboardsViewProjectionWrite[customViewProjection].CameraPosition; billboard.DistanceSquared = (float)Vector3D.DistanceSquared(cameraPosition, origin); // Color billboard.Color = color; billboard.ColorIntensity = 1; billboard.Reflectivity = reflectivity; billboard.CustomViewProjection = customViewProjection; billboard.ParentID = -1; billboard.SoftParticleDistanceScale = 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; }
static void PreGatherBillboard(MyBillboard billboard) { var material = MyTransparentMaterials.GetMaterial(billboard.Material); if (material.NeedSort) { m_sortedCount++; } else { m_unsortedCount++; } }
public static VRageRender.MyBillboard AddBillboardEffect(MyParticleEffect effect) { //VRageRender.MyBillboard billboard = m_preallocatedParticleBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard != null) { MyTransparentGeometry.StartParticleProfilingBlock("AddBillboardEffect"); billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, effect.WorldMatrix.Translation); billboard.CustomViewProjection = -1; MyTransparentGeometry.EndParticleProfilingBlock(); } return(billboard); }
public void PrepareForDraw(ref VRageRender.MyBillboard effectBillboard) { m_billboards.Clear(); if (m_particles.Count == 0) { return; } if (UseLayerSorting && effectBillboard == null) { effectBillboard = MyTransparentGeometry.AddBillboardEffect(m_effect); if (effectBillboard != null) { m_billboards.Add(effectBillboard); } } using (ParticlesLock.AcquireSharedUsing()) { foreach (MyAnimatedParticle particle in m_particles) { MyTransparentGeometry.StartParticleProfilingBlock("m_preallocatedBillboards.Allocate()"); VRageRender.MyBillboard billboard = MyTransparentGeometry.AddBillboardParticle(particle, effectBillboard, !UseLayerSorting); if (billboard != null) { if (!UseLayerSorting) { billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); m_billboards.Add(billboard); } } MyTransparentGeometry.EndParticleProfilingBlock(); if (billboard == null) { break; } } } }
/// <summary>Compare using squared distance from camera</summary> public int Compare(int x, int y) { MyBillboard billx = m_sortedBuffer[x]; MyBillboard billy = m_sortedBuffer[y]; if (billx.DistanceSquared < billy.DistanceSquared) { return(-1); } else if (billx.DistanceSquared == billy.DistanceSquared) { return(0); } else { return(1); } }
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++; } }
// Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc). // It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare). public static void AddPointBillboard(string material, Vector4 color, Vector3D origin, int renderObjectID, ref MatrixD worldToLocal, float radius, float angle, int customViewProjection = -1, MyBillboard.BlenType blendType = MyBillboard.BlenType.Standard) { Debug.Assert(material != null); if (!IsEnabled) { return; } MyDebug.AssertIsValid(origin); MyDebug.AssertIsValid(angle); MyQuadD quad; Vector3 diff = MyTransparentGeometry.Camera.Translation - origin; if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, radius, angle, (origin + (Vector3D)MyTransparentGeometry.Camera.Forward * diff.Length())) != false) { VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } CreateBillboard(billboard, ref quad, material, ref color, ref origin, customViewProjection); billboard.BlendType = blendType; if (renderObjectID != -1) { Vector3D.Transform(ref billboard.Position0, ref worldToLocal, out billboard.Position0); Vector3D.Transform(ref billboard.Position1, ref worldToLocal, out billboard.Position1); Vector3D.Transform(ref billboard.Position2, ref worldToLocal, out billboard.Position2); Vector3D.Transform(ref billboard.Position3, ref worldToLocal, out billboard.Position3); billboard.ParentID = renderObjectID; } VRageRender.MyRenderProxy.AddBillboard(billboard); } }
// Add billboard for one frame only. This billboard isn't particle (it doesn't survive this frame, doesn't have update/draw methods, etc). // It's used by other classes when they want to draw some billboard (e.g. rocket thrusts, reflector glare). public static void AddPointBillboard(string material, Color color, Vector3D origin, int renderObjectID, ref MatrixD worldToLocal, float radius, float angle, int priority = 0, bool colorize = false, bool near = false, bool lowres = false, int customViewProjection = -1) { Debug.Assert(material != null); if (!IsEnabled) { return; } MyDebug.AssertIsValid(origin); MyDebug.AssertIsValid(angle); MyQuadD quad; if (MyUtils.GetBillboardQuadAdvancedRotated(out quad, origin, radius, radius, angle, MyTransparentGeometry.Camera.Translation) != false) { VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard == null) { return; } billboard.Priority = priority; CreateBillboard(billboard, ref quad, material, ref color, ref origin, colorize, near, lowres, customViewProjection); if (renderObjectID != -1) { Vector3D.Transform(ref billboard.Position0, ref worldToLocal, out billboard.Position0); Vector3D.Transform(ref billboard.Position1, ref worldToLocal, out billboard.Position1); Vector3D.Transform(ref billboard.Position2, ref worldToLocal, out billboard.Position2); Vector3D.Transform(ref billboard.Position3, ref worldToLocal, out billboard.Position3); billboard.ParentID = renderObjectID; } VRageRender.MyRenderProxy.AddBillboard(billboard); } }
public static VRageRender.MyBillboard AddBillboardParticle(MyAnimatedParticle particle) { //MyBillboard billboard = m_preallocatedParticleBillboards.Allocate(); //VRageRender.MyBillboard billboard = new VRageRender.MyBillboard(); VRageRender.MyBillboard billboard = VRageRender.MyRenderProxy.BillboardsPoolWrite.Allocate(); if (billboard != null) { MyTransparentGeometry.StartParticleProfilingBlock("item.Value.Draw"); billboard.BlendType = MyBillboard.BlenType.Standard; if (particle.Draw(billboard) == true) { billboard.CustomViewProjection = -1; } else { billboard = null; } MyTransparentGeometry.EndParticleProfilingBlock(); } return(billboard); }
private static void GetBillboardQuadRotated(VRageRender.MyBillboard billboard, ref Vector3D position, Vector2 radius, ref Matrix transform) { GetBillboardQuadRotated(billboard, ref position, radius, ref transform, MyTransparentGeometry.Camera.Left, MyTransparentGeometry.Camera.Up); }
public static void AddBillboard(MyBillboard billboard) { if (!DebugOverrides.BillboardsStatic) return; System.Diagnostics.Debug.Assert(billboard != null); billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); BillboardsWrite.Add(billboard); }
// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(VRageRender.MyBillboard billboard) { if (Pivot != null) { if (PivotRotation != null) { Matrix pivotRotationTransform = Matrix.CreateRotationX(MathHelper.ToRadians(m_actualPivotRotation.X) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationY(MathHelper.ToRadians(m_actualPivotRotation.Y) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS) * Matrix.CreateRotationZ(MathHelper.ToRadians(m_actualPivotRotation.Z) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS); m_actualPivot = Vector3.TransformNormal(m_actualPivot, pivotRotationTransform); } m_actualPivot = Vector3D.TransformNormal(m_actualPivot, m_generation.GetEffect().WorldMatrix); } var actualPosition = m_actualPosition + m_actualPivot; MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting billboard.DistanceSquared = (float)Vector3D.DistanceSquared(MyTransparentGeometry.Camera.Translation, actualPosition); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 0.1f) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); float actualAlphaCutout = 0; if (AlphaCutout != null) { MyTransparentGeometry.StartParticleProfilingBlock("AlphaCutout calculation"); AlphaCutout.GetInterpolatedValue <float>(m_normalizedTime, out actualAlphaCutout); MyTransparentGeometry.EndParticleProfilingBlock(); } billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = m_generation.GetEffect().LowRes || VRageRender.MyRenderConstants.RenderQualityProfile.LowResParticles; billboard.CustomViewProjection = -1; billboard.ParentID = -1; billboard.AlphaCutout = actualAlphaCutout; billboard.UVOffset = Vector2.Zero; billboard.UVSize = Vector2.One; float alpha = 1; Matrix transform = Matrix.Identity; Vector3 normal = Vector3.Forward; Vector3 actualVelocity = (Vector3)(m_actualPosition - m_previousPosition); float radiusBySpeed = m_generation.RadiusBySpeed; if (radiusBySpeed > 0) { float actualSpeed = actualVelocity.Length(); actualRadius = Math.Max(actualRadius, actualRadius * m_generation.RadiusBySpeed * actualSpeed); } if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); Vector2 actualRadiusV2 = new Vector2(actualRadius, actualRadius); if (Thickness > 0) { actualRadiusV2.Y = Thickness; } if (m_generation.RotationReference == MyRotationReference.Camera) { transform = Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(MyTransparentGeometry.Camera.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, MyTransparentGeometry.Camera.Left, MyTransparentGeometry.Camera.Up); } else if (m_generation.RotationReference == MyRotationReference.Local) { transform = Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(m_generation.GetEffect().WorldMatrix.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, m_generation.GetEffect().WorldMatrix.Left, m_generation.GetEffect().WorldMatrix.Up); } else if (m_generation.RotationReference == MyRotationReference.Velocity) { if (actualVelocity.LengthSquared() < 0.00001f) { return(false); } Matrix velocityRef = Matrix.CreateFromDir(Vector3.Normalize(actualVelocity)); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.VelocityAndCamera) { if (actualVelocity.LengthSquared() < 0.0001f) { return(false); } Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 velocityDir = Vector3.Normalize(actualVelocity); Vector3 sideVector = Vector3.Cross(cameraToPoint, velocityDir); Vector3 upVector = Vector3.Cross(sideVector, velocityDir); Matrix velocityRef = Matrix.CreateWorld(m_actualPosition, velocityDir, upVector); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else if (m_generation.RotationReference == MyRotationReference.LocalAndCamera) { Vector3 cameraToPoint = Vector3.Normalize(m_actualPosition - MyTransparentGeometry.Camera.Translation); Vector3 localDir = m_generation.GetEffect().WorldMatrix.Forward; Vector3 sideVector = Vector3.Cross(cameraToPoint, localDir); Vector3 upVector = Vector3.Cross(sideVector, localDir); Matrix velocityRef = Matrix.CreateWorld(m_actualPosition, localDir, upVector); transform = Matrix.CreateFromAxisAngle(velocityRef.Right, m_actualAngle.X) * Matrix.CreateFromAxisAngle(velocityRef.Up, m_actualAngle.Y) * Matrix.CreateFromAxisAngle(velocityRef.Forward, m_actualAngle.Z); GetBillboardQuadRotated(billboard, ref actualPosition, actualRadiusV2, ref transform, velocityRef.Left, velocityRef.Up); } else { System.Diagnostics.Debug.Fail("Unknown RotationReference enum"); } MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyUtils.GetRandomVector3Normalized(); } MyQuadD quad = new MyQuadD(); MyPolyLineD polyLine = new MyPolyLineD(); //polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); if (actualVelocity.LengthSquared() > 0) { polyLine.LineDirectionNormalized = MyUtils.Normalize(actualVelocity); } else { polyLine.LineDirectionNormalized = MyUtils.Normalize(Velocity); } if (m_actualAngle.Z != 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(m_actualAngle.Z)); } polyLine.Point0 = actualPosition; polyLine.Point1.X = actualPosition.X - polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = actualPosition.Y - polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = actualPosition.Z - polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle.LengthSquared() > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; var camPos = MyTransparentGeometry.Camera.Translation; MyUtils.GetPolyLineQuad(out quad, ref polyLine, camPos); transform.Forward = polyLine.LineDirectionNormalized; billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; } else { throw new NotSupportedException(Type + " is not supported particle type"); } if (this.m_generation.AlphaAnisotropic) { normal = Vector3.Normalize(Vector3.Cross(billboard.Position0 - billboard.Position1, billboard.Position0 - billboard.Position2)); Vector3 forward = (billboard.Position0 + billboard.Position1 + billboard.Position2 + billboard.Position3) / 4 - MyTransparentGeometry.Camera.Translation; //Vector3 forward = MyTransparentGeometry.Camera.Forward; float angle = Math.Abs(Vector3.Dot(MyUtils.Normalize(forward), normal)); float alphaCone = 1 - (float)Math.Pow(1 - angle, 4); alpha = alphaCone; } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color = Vector4.One; if (Color.GetKeysCount() > 0) { Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); } if (m_arrayIndex != -1) { Vector3 arraySize = m_generation.ArraySize; if (arraySize.X > 0 && arraySize.Y > 0) { int arrayOffset = m_generation.ArrayOffset; int arrayModulo = m_generation.ArrayModulo == 0 ? (int)arraySize.X * (int)arraySize.Y : m_generation.ArrayModulo; m_arrayIndex = m_arrayIndex % arrayModulo + arrayOffset; float xDiv = 1.0f / arraySize.X; float yDiv = 1.0f / arraySize.Y; int xIndex = m_arrayIndex % (int)arraySize.X; int yIndex = m_arrayIndex / (int)arraySize.X; billboard.UVOffset = new Vector2(xDiv * xIndex, yDiv * yIndex); billboard.UVSize = new Vector2(xDiv, yDiv); } } var material1 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); var material2 = MyTransparentMaterials.GetMaterial("ErrorMaterial"); float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); if (material1 != null) { billboard.Material = material1.Name; } billboard.BlendMaterial = material2.Name; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; billboard.ColorIntensity = ColorIntensity; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
/// <returns>True if window has decals and is not too far</returns> static bool HandleWindow(MyBillboard billboard) { uint parentID = (uint)billboard.ParentID; if (MyScreenDecals.HasEntityDecals(parentID) && billboard.DistanceSquared < MyScreenDecals.VISIBLE_DECALS_SQ_TH) { m_windowsWithDecals.Add(parentID); return true; } return false; }
public static void AddBillboard(MyBillboard billboard) { System.Diagnostics.Debug.Assert(billboard != null); billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); BillboardsWrite.Add(billboard); }
private static void SetupCustomViewProjection(MyEffectTransparentGeometry effect, ref Viewport originalViewport, MyBillboard lastBillboard, ref bool ignoreDepth, ref Matrix projectionMatrix) { if (lastBillboard.CustomViewProjection != -1 && MyRenderProxy.BillboardsViewProjectionRead.ContainsKey(lastBillboard.CustomViewProjection)) { var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[lastBillboard.CustomViewProjection]; effect.SetViewMatrix(ref billboardViewProjection.ViewAtZero); effect.SetProjectionMatrix(ref billboardViewProjection.Projection); Matrix invProjectionMatrix = Matrix.Invert((MyRenderCamera.m_backupMatrix.HasValue ? MyRenderCamera.m_backupMatrix.Value : MyRenderCamera.ProjectionMatrix)); effect.SetInverseDefaultProjectionMatrix(ref invProjectionMatrix); Viewport viewport = new Viewport((int)billboardViewProjection.Viewport.OffsetX, (int)billboardViewProjection.Viewport.OffsetY, (int)billboardViewProjection.Viewport.Width, (int)billboardViewProjection.Viewport.Height); if (MyRender.GetScreenshot() != null) viewport = new Viewport((int)(billboardViewProjection.Viewport.OffsetX * MyRender.GetScreenshot().SizeMultiplier.X), (int)(billboardViewProjection.Viewport.OffsetY * MyRender.GetScreenshot().SizeMultiplier.Y), (int)(billboardViewProjection.Viewport.Width * MyRender.GetScreenshot().SizeMultiplier.X), (int)(billboardViewProjection.Viewport.Height * MyRender.GetScreenshot().SizeMultiplier.Y)); MyRender.SetDeviceViewport(viewport); ignoreDepth = !billboardViewProjection.DepthRead; projectionMatrix = billboardViewProjection.Projection; } else { var viewMatrix = MyRenderCamera.ViewMatrixAtZero; effect.SetViewMatrix(ref viewMatrix); effect.SetProjectionMatrix(ref MyRenderCamera.ProjectionMatrix); MyRender.SetDeviceViewport(originalViewport); ignoreDepth = false; projectionMatrix = MyRenderCamera.ProjectionMatrix; } }
public static void CreateBillboard(VRageRender.MyBillboard billboard, ref MyQuadD quad, string material, ref Vector4 color, ref Vector3D origin, int customViewProjection = -1, float reflection = 0) { CreateBillboard(billboard, ref quad, material, ref color, ref origin, Vector2.Zero, customViewProjection, reflection); }
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++; }
private static bool DefaultWindowHanlder(MyBillboard billboard) { return(true); }
/// <summary> /// Copies the billboard to vertex buffer. /// </summary> /// <param name="billboarIdx">The billboar idx.</param> static void CopyBillboardToVertices(int billboarIdx, MyBillboard billboard) { int startIndex = (billboarIdx) * MyTransparentGeometryConstants.VERTICES_PER_TRANSPARENT_GEOMETRY; HalfVector4 colorHalf = new HalfVector4(billboard.Color); MyTransparentMaterial materialProperties = MyTransparentMaterials.GetMaterial(billboard.Material); billboard.Position0.AssertIsValid(); billboard.Position1.AssertIsValid(); billboard.Position2.AssertIsValid(); billboard.Position3.AssertIsValid(); m_vertices[startIndex + 0].Color = colorHalf; m_vertices[startIndex + 0].TexCoord = new HalfVector4(materialProperties.UVOffset.X + billboard.UVOffset.X, materialProperties.UVOffset.Y + billboard.UVOffset.Y, billboard.BlendTextureRatio, materialProperties.Emissivity); m_vertices[startIndex + 1].Color = colorHalf; m_vertices[startIndex + 1].TexCoord = new HalfVector4(materialProperties.UVOffset.X + materialProperties.UVSize.X + billboard.UVOffset.X, materialProperties.UVOffset.Y + billboard.UVOffset.Y, billboard.BlendTextureRatio, materialProperties.Emissivity); m_vertices[startIndex + 2].Color = colorHalf; m_vertices[startIndex + 2].TexCoord = new HalfVector4(materialProperties.UVOffset.X + materialProperties.UVSize.X + billboard.UVOffset.X, materialProperties.UVOffset.Y + materialProperties.UVSize.Y + billboard.UVOffset.Y, billboard.BlendTextureRatio, materialProperties.Emissivity); m_vertices[startIndex + 3].Color = colorHalf; m_vertices[startIndex + 3].TexCoord = new HalfVector4(materialProperties.UVOffset.X + billboard.UVOffset.X, materialProperties.UVOffset.Y + materialProperties.UVSize.Y + billboard.UVOffset.Y, billboard.BlendTextureRatio, materialProperties.Emissivity); Vector3D pos0 = billboard.Position0; Vector3D pos1 = billboard.Position1; Vector3D pos2 = billboard.Position2; Vector3D pos3 = billboard.Position3; if (billboard.ParentID != -1) { MyRenderObject renderObject; if (MyRender.m_renderObjects.TryGetValue((uint)billboard.ParentID, out renderObject)) { MyRenderTransformObject transformObject = renderObject as MyRenderTransformObject; MyManualCullableRenderObject cullableObject = renderObject as MyManualCullableRenderObject; if (transformObject != null) { var worldMatrix = transformObject.WorldMatrix; Vector3D.Transform(ref pos0, ref worldMatrix, out pos0); Vector3D.Transform(ref pos1, ref worldMatrix, out pos1); Vector3D.Transform(ref pos2, ref worldMatrix, out pos2); Vector3D.Transform(ref pos3, ref worldMatrix, out pos3); } else if (cullableObject != null) { var worldMatrix = cullableObject.WorldMatrix; Vector3D.Transform(ref pos0, ref worldMatrix, out pos0); Vector3D.Transform(ref pos1, ref worldMatrix, out pos1); Vector3D.Transform(ref pos2, ref worldMatrix, out pos2); Vector3D.Transform(ref pos3, ref worldMatrix, out pos3); } } } if (billboard.CustomViewProjection != -1) { System.Diagnostics.Debug.Assert(MyRenderProxy.BillboardsViewProjectionRead.ContainsKey(billboard.CustomViewProjection)); if (MyRenderProxy.BillboardsViewProjectionRead.ContainsKey(billboard.CustomViewProjection)) { var billboardViewProjection = MyRenderProxy.BillboardsViewProjectionRead[billboard.CustomViewProjection]; pos0 -= billboardViewProjection.CameraPosition; pos1 -= billboardViewProjection.CameraPosition; pos2 -= billboardViewProjection.CameraPosition; pos3 -= billboardViewProjection.CameraPosition; } else { pos0 -= MyRenderCamera.Position; pos1 -= MyRenderCamera.Position; pos2 -= MyRenderCamera.Position; pos3 -= MyRenderCamera.Position; } } else { pos0 -= MyRenderCamera.Position; pos1 -= MyRenderCamera.Position; pos2 -= MyRenderCamera.Position; pos3 -= MyRenderCamera.Position; } m_vertices[startIndex + 0].Position = pos0; m_vertices[startIndex + 1].Position = pos1; m_vertices[startIndex + 2].Position = pos2; m_vertices[startIndex + 3].Position = pos3; pos0.AssertIsValid(); pos1.AssertIsValid(); pos2.AssertIsValid(); pos3.AssertIsValid(); if (materialProperties.Reflectivity > 0) { var normal = Vector3.Cross(billboard.Position1 - billboard.Position0, billboard.Position2 - billboard.Position0); var NormalRefl = new HalfVector4(normal.X, normal.Y, normal.Z, billboard.Reflectivity); m_vertices[startIndex + 0].TexCoord2 = NormalRefl; m_vertices[startIndex + 1].TexCoord2 = NormalRefl; m_vertices[startIndex + 2].TexCoord2 = NormalRefl; m_vertices[startIndex + 3].TexCoord2 = NormalRefl; } else if (billboard.BlendTextureRatio > 0) { MyTransparentMaterial blendMaterialProperties = MyTransparentMaterials.GetMaterial(billboard.BlendMaterial); m_vertices[startIndex + 0].TexCoord2 = new HalfVector4(blendMaterialProperties.UVOffset.X + billboard.UVOffset.X, blendMaterialProperties.UVOffset.Y + billboard.UVOffset.Y, 0, 0); m_vertices[startIndex + 1].TexCoord2 = new HalfVector4(blendMaterialProperties.UVOffset.X + blendMaterialProperties.UVSize.X + billboard.UVOffset.X, blendMaterialProperties.UVOffset.Y + billboard.UVOffset.Y, 0, 0); m_vertices[startIndex + 2].TexCoord2 = new HalfVector4(blendMaterialProperties.UVOffset.X + blendMaterialProperties.UVSize.X + billboard.UVOffset.X, blendMaterialProperties.UVOffset.Y + blendMaterialProperties.UVSize.Y + billboard.UVOffset.Y, 0, 0); m_vertices[startIndex + 3].TexCoord2 = new HalfVector4(blendMaterialProperties.UVOffset.X + billboard.UVOffset.X, blendMaterialProperties.UVOffset.Y + blendMaterialProperties.UVSize.Y + billboard.UVOffset.Y, 0, 0); } }
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); }