Exemple #1
0
    private void UpdateBackground()
    {
        if (starfieldGameObject != null)
        {
            if (starfieldInBackground == true)
            {
                if (starfieldCamera != null)
                {
                    // Stretch to camera's far view frustum
                    if (distributionRadius != 0.0f)
                    {
                        var scale = SGT_Helper.NewVector3(starfieldCamera.farClipPlane / distributionRadius) * 0.9f;

                        SGT_Helper.SetLocalScale(starfieldGameObject.transform, scale);
                    }

                    // Centre to main camera
                    SGT_Helper.SetPosition(starfieldGameObject.transform, starfieldCamera.transform.position);
                }
            }
            else
            {
                SGT_Helper.SetLocalPosition(starfieldGameObject.transform, Vector3.zero);
                SGT_Helper.SetLocalScale(starfieldGameObject.transform, Vector3.one);
            }
        }
    }
    private void UpdateShader()
    {
        var position            = transform.position;
        var lightSourcePosition = SGT_Helper.GetPosition(ringLightSource);
        var uniformScale        = UniformScale;
        var starPositionRaw     = ringGameObject.transform.worldToLocalMatrix.MultiplyPoint(lightSourcePosition);

        ringMaterial.SetTexture("dayTexture", asteroidTextureDay);
        ringMaterial.SetTexture("nightTexture", asteroidTextureNight);
        ringMaterial.SetTexture("bumpTexture", asteroidTextureHeight);
        ringMaterial.SetVector("starPositionRaw", SGT_Helper.NewVector4(starPositionRaw, 1.0f));
        ringMaterial.SetVector("centrePosition", position);
        ringMaterial.SetFloat("ringHeight", ringHeight);

        if (shadow == true)
        {
            var shadowRatio = 0.0f;
            var shadowScale = 0.0f;

            if (shadowWidth > 0.0f)
            {
                shadowRatio = ShadowInnerRadius / ShadowOuterRadius;
                shadowScale = 1.0f / (1.0f - shadowRatio);
            }

            ringMaterial.SetColor("umbraColour", shadowUmbraColour);
            ringMaterial.SetColor("penumbraColour", shadowPenumbraColour);
            ringMaterial.SetFloat("shadowRatio", shadowRatio);
            ringMaterial.SetFloat("shadowScale", shadowScale);

            if (ShadowInnerRadius > 0.0f)
            {
                var direction = (position - lightSourcePosition).normalized;
                var r         = Quaternion.FromToRotation(direction, Vector3.forward);
                var s         = SGT_Helper.NewVector3(1.0f / (ShadowOuterRadius * uniformScale));

                var shadowT = SGT_MatrixHelper.Translation(-position);
                var shadowR = SGT_MatrixHelper.Rotation(r);
                var shadowS = SGT_MatrixHelper.Scaling(s);

                var shadowMatrix = shadowS * shadowR * shadowT;

                ringMaterial.SetMatrix("shadowMatrix", shadowMatrix);
            }
        }

        if (spin == true)
        {
            ringMaterial.SetFloat("spinRateMax", spinRateMax);
        }
    }
    private void StepScale()
    {
        if (parent == null)
        {
            parent = SGT_Helper.GetComponentUpwards <SGT_DebrisSpawner>(gameObject);
        }

        if (parent != null)
        {
            var position = SGT_Helper.GetPosition(parent.DebrisCentre);
            var distance = (position - transform.position).magnitude;
            var scaleMul = 1.0f - SGT_Helper.RemapClamped(parent.DebrisContainerInnerRadius, parent.DebrisContainerRadius, distance, 0.0f, 1.0f);

            SGT_Helper.SetLocalScale(transform, SGT_Helper.NewVector3(scale * scaleMul));
        }
    }
    private void UpdateTransform()
    {
        var oblatenessScale       = new Vector3(1.0f, 1.0f - surfaceOblateness, 1.0f);
        var surfaceScale          = SGT_Helper.NewVector3(SurfaceEquatorialRadius);
        var atmosphereScale       = SGT_Helper.NewVector3(AtmosphereEquatorialRadius);
        var starObserverPosition  = SGT_Helper.GetPosition(starObserver);
        var starObserverDirection = (starObserverPosition - atmosphereGameObject.transform.position).normalized;

        SGT_Helper.SetLocalScale(oblatenessGameObject.transform, oblatenessScale);
        SGT_Helper.SetLocalScale(surfaceGameObject.transform, surfaceScale);
        SGT_Helper.SetLocalScale(atmosphereGameObject.transform, atmosphereScale);

        if (atmosphereGameObject.transform.up != starObserverDirection)
        {
            atmosphereGameObject.transform.up = starObserverDirection;

            SGT_Helper.UpdateNonOrthogonalTransform(atmosphereGameObject.transform);
        }
    }
Exemple #5
0
    private void CreateMesh(ParticleList particles)
    {
        SGT_Helper.DestroyObject(generatedMesh);

        particleCount = particles.Count;
        generatedMesh = new Mesh();

        var positions = new Vector3[particleCount * 4];
        var indices   = new int[particleCount * 6];
        var uv0s      = new Vector2[particleCount * 4];
        var uv1s      = new Vector2[particleCount * 4];
        var normals   = new Vector3[particleCount * 4];
        var colours   = new Color[particleCount * 4];

        for (var i = 0; i < particleCount; i++)
        {
            var particle = particles[i];

            var i0 = i * 6;
            var i1 = i0 + 1;
            var i2 = i1 + 1;
            var i3 = i2 + 1;
            var i4 = i3 + 1;
            var i5 = i4 + 1;

            var v0 = i * 4;
            var v1 = v0 + 1;
            var v2 = v1 + 1;
            var v3 = v2 + 1;

            // Index data
            indices[i0] = v0;
            indices[i1] = v1;
            indices[i2] = v2;
            indices[i3] = v3;
            indices[i4] = v2;
            indices[i5] = v1;

            var right = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, particle.Angle);
            var up    = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, particle.Angle);
            var uv1   = new Vector2(particle.Size * 0.5f, 0.0f);

            // Write star values into vertex data
            positions[v0] = particle.Position;
            positions[v1] = particle.Position;
            positions[v2] = particle.Position;
            positions[v3] = particle.Position;

            normals[v0] = SGT_Helper.NewVector3(-right + up, 0.0f);
            normals[v1] = SGT_Helper.NewVector3(right + up, 0.0f);
            normals[v2] = SGT_Helper.NewVector3(-right - up, 0.0f);
            normals[v3] = SGT_Helper.NewVector3(right - up, 0.0f);

            colours[v0] = particle.Colour;
            colours[v1] = particle.Colour;
            colours[v2] = particle.Colour;
            colours[v3] = particle.Colour;

            uv0s[v0] = new Vector2(0.0f, 1.0f);
            uv0s[v1] = new Vector2(1.0f, 1.0f);
            uv0s[v2] = new Vector2(0.0f, 0.0f);
            uv0s[v3] = new Vector2(1.0f, 0.0f);

            uv1s[v0] = uv1;
            uv1s[v1] = uv1;
            uv1s[v2] = uv1;
            uv1s[v3] = uv1;
        }

        generatedMesh.name      = "Dust";
        generatedMesh.vertices  = positions;
        generatedMesh.normals   = normals;
        generatedMesh.colors    = colours;
        generatedMesh.uv        = uv0s;
        generatedMesh.uv2       = uv1s;
        generatedMesh.triangles = indices;
        generatedMesh.bounds    = new Bounds(Vector3.zero, new Vector3(100000000.0f, 100000000.0f, 100000000.0f));         // NOTE: using infinity here causes an error

        dustMesh.SharedMesh = generatedMesh;
        dustMesh.Update();
    }
Exemple #6
0
    private void CreateMesh(ParticleList particles)
    {
        SGT_Helper.DestroyObject(generatedMesh);

        particleCount = particles.Count;
        generatedMesh = new Mesh();

        var positions = new Vector3[particleCount * 4];
        var indices   = new int[particleCount * 6];
        var uv0s      = new Vector2[particleCount * 4];
        var uv1s      = new Vector2[particleCount * 4];
        var normals   = new Vector3[particleCount * 4];
        var colours   = new Color[particleCount * 4];
        var bounds    = new Bounds();

        for (var i = 0; i < particleCount; i++)
        {
            var particle = particles[i];

            var i0 = i * 6;
            var i1 = i0 + 1;
            var i2 = i1 + 1;
            var i3 = i2 + 1;
            var i4 = i3 + 1;
            var i5 = i4 + 1;

            var v0 = i * 4;
            var v1 = v0 + 1;
            var v2 = v1 + 1;
            var v3 = v2 + 1;

            // Index data
            indices[i0] = v0;
            indices[i1] = v1;
            indices[i2] = v2;
            indices[i3] = v3;
            indices[i4] = v2;
            indices[i5] = v1;

            var right = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, particle.Angle);
            var up    = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, particle.Angle);
            var uv1   = new Vector2(particle.Size * 0.5f, 0.0f);

            bounds.Encapsulate(particle.Position);

            // Write star values into vertex data
            positions[v0] = particle.Position;
            positions[v1] = particle.Position;
            positions[v2] = particle.Position;
            positions[v3] = particle.Position;

            normals[v0] = SGT_Helper.NewVector3(-right + up, 0.0f);
            normals[v1] = SGT_Helper.NewVector3(right + up, 0.0f);
            normals[v2] = SGT_Helper.NewVector3(-right - up, 0.0f);
            normals[v3] = SGT_Helper.NewVector3(right - up, 0.0f);

            colours[v0] = particle.Colour;
            colours[v1] = particle.Colour;
            colours[v2] = particle.Colour;
            colours[v3] = particle.Colour;

            uv0s[v0] = new Vector2(0.0f, 1.0f);
            uv0s[v1] = new Vector2(1.0f, 1.0f);
            uv0s[v2] = new Vector2(0.0f, 0.0f);
            uv0s[v3] = new Vector2(1.0f, 0.0f);

            uv1s[v0] = uv1;
            uv1s[v1] = uv1;
            uv1s[v2] = uv1;
            uv1s[v3] = uv1;
        }

        bounds.Expand(particleScale);

        generatedMesh.hideFlags = HideFlags.DontSave;
        generatedMesh.name      = "Nebula";
        generatedMesh.bounds    = bounds;
        generatedMesh.vertices  = positions;
        generatedMesh.normals   = normals;
        generatedMesh.colors    = colours;
        generatedMesh.uv        = uv0s;
        generatedMesh.uv1       = uv1s;
        generatedMesh.triangles = indices;

        nebulaMesh.SharedMesh = generatedMesh;
        nebulaMesh.Update();
    }
    private void UpdateShader()
    {
        var uniformScale        = UniformScale;
        var position            = transform.position;
        var lightSourcePosition = SGT_Helper.GetPosition(lightSource);

        ringMaterial.SetTexture("ringTexture", ringTexture);
        ringMaterial.SetVector("position", position);
        ringMaterial.SetFloat("ringRadius", RingRadiusInner * uniformScale);
        ringMaterial.SetFloat("ringThickness", ringWidth * uniformScale);

        if (shadow == true)
        {
            var shadowRatio = 0.0f;
            var shadowScale = 0.0f;

            if (shadowWidth > 0.0f)
            {
                shadowRatio = ShadowInnerRadius / ShadowOuterRadius;
                shadowScale = 1.0f / (1.0f - shadowRatio);
            }

            ringMaterial.SetColor("umbraColour", shadowUmbraColour);
            ringMaterial.SetColor("penumbraColour", shadowPenumbraColour);
            ringMaterial.SetFloat("shadowRatio", shadowRatio);
            ringMaterial.SetFloat("shadowScale", shadowScale);

            if (ShadowInnerRadius > 0.0f)
            {
                var direction = (position - lightSourcePosition).normalized;
                var r         = Quaternion.FromToRotation(direction, Vector3.forward);
                var s         = SGT_Helper.NewVector3(1.0f / (ShadowOuterRadius * uniformScale));

                var shadowT = SGT_MatrixHelper.Translation(-position);
                var shadowR = SGT_MatrixHelper.Rotation(r);
                var shadowS = SGT_MatrixHelper.Scaling(s);

                var shadowMatrix = shadowS * shadowR * shadowT;

                ringMaterial.SetMatrix("shadowMatrix", shadowMatrix);
            }
        }

        if (lit == true)
        {
            ringMaterial.SetVector("starDirection", StarDirection);
            ringMaterial.SetFloat("ringBrightness", (litBrightnessMin + litBrightnessMax) * 0.5f);
            ringMaterial.SetFloat("ringBrightnessRange", litBrightnessMax - litBrightnessMin);
        }

        if (scattering == true)
        {
            ringMaterial.SetVector("starPosition", lightSourcePosition);

            var mie  = -(1.0f - 1.0f / Mathf.Pow(10.0f, scatteringMie * 5.0f));
            var mie4 = new Vector4(mie * 2.0f, 1.0f - mie * mie, 1.0f + mie * mie, 1.5f);

            ringMaterial.SetVector("mieValues", mie4);
            ringMaterial.SetFloat("occlusion", scatteringOcclusion);
        }
    }
Exemple #8
0
    public void WriteStar(SGT_StarfieldStarData ssd, int starIndex)
    {
        if (ssd != null)
        {
            var po = packer.GetOutput(ssd.TextureIndex);

            if (po != null)
            {
                SGT_MeshData meshData;
                int          vertexIndex;

                if (FindStar(starIndex, out meshData, out vertexIndex) == true)
                {
                    var v0       = vertexIndex;
                    var v1       = v0 + 1;
                    var v2       = v1 + 1;
                    var v3       = v2 + 1;
                    var position = ssd.Position;
                    var uv1      = new Vector2((ssd.RadiusMin + ssd.RadiusMax) * 0.5f, (ssd.RadiusMax - ssd.RadiusMin) * 0.5f);
                    var colour   = new Color(ssd.RadiusPulseRate, ssd.RadiusPulseOffset, 0.0f, 0.0f);
                    var right    = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, ssd.Angle);
                    var up       = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, ssd.Angle);

                    if (meshData.Positions[v0] != position)
                    {
                        meshData.Positions[v0] = position;
                        meshData.Positions[v1] = position;
                        meshData.Positions[v2] = position;
                        meshData.Positions[v3] = position;

                        meshData.Modified = true;
                    }

                    if (meshData.Normals[v0] != SGT_Helper.NewVector3(-right + up, 0.0f))
                    {
                        meshData.Normals[v0] = SGT_Helper.NewVector3(-right + up, 0.0f);
                        meshData.Normals[v1] = SGT_Helper.NewVector3(right + up, 0.0f);
                        meshData.Normals[v2] = SGT_Helper.NewVector3(-right - up, 0.0f);
                        meshData.Normals[v3] = SGT_Helper.NewVector3(right - up, 0.0f);

                        meshData.Modified = true;
                    }

                    if (meshData.Uv0s[v0] != po.UvTopLeft && meshData.Uv0s[v3] != po.UvBottomRight)
                    {
                        meshData.Uv0s[v0] = po.UvTopLeft;
                        meshData.Uv0s[v1] = po.UvTopRight;
                        meshData.Uv0s[v2] = po.UvBottomLeft;
                        meshData.Uv0s[v3] = po.UvBottomRight;

                        meshData.Modified = true;
                    }

                    if (meshData.Uv1s[v0] != uv1)
                    {
                        meshData.Uv1s[v0] = uv1;
                        meshData.Uv1s[v1] = uv1;
                        meshData.Uv1s[v2] = uv1;
                        meshData.Uv1s[v3] = uv1;

                        meshData.Modified = true;
                    }

                    if (meshData.Colours[v0] != colour)
                    {
                        meshData.Colours[v0] = colour;
                        meshData.Colours[v1] = colour;
                        meshData.Colours[v2] = colour;
                        meshData.Colours[v3] = colour;

                        meshData.Modified = true;
                    }
                }
            }
        }
    }
    private Mesh GenerateAsteroidMesh(int asteroidCount)
    {
        var indices         = new int[asteroidCount * 6];
        var positions       = new Vector3[asteroidCount * 4];
        var normals         = new Vector3[asteroidCount * 4];
        var colours         = new Color[asteroidCount * 4];
        var uv0s            = new Vector2[asteroidCount * 4];
        var uv1s            = new Vector2[asteroidCount * 4];
        var size            = (ringRadius + ringWidth + asteroidRadiusMax) * 2.0f;
        var bounds          = new Bounds(Vector3.zero, new Vector3(size, asteroidRadiusMax * 2.0f, size));
        var uvStep          = new Vector2(1.0f / (float)asteroidTextureTilesX, 1.0f / (float)asteroidTextureTilesY);
        var ringRadiusInner = RingRadiusInner;
        var ringRadiusOuter = RingRadiusOuter;

        for (var i = 0; i < asteroidCount; i++)
        {
            // Index data
            var indicesIndex = i * 6;
            var vertexIndex  = i * 4;

            indices[indicesIndex + 0] = vertexIndex + 0;
            indices[indicesIndex + 1] = vertexIndex + 1;
            indices[indicesIndex + 2] = vertexIndex + 2;
            indices[indicesIndex + 3] = vertexIndex + 3;
            indices[indicesIndex + 4] = vertexIndex + 2;
            indices[indicesIndex + 5] = vertexIndex + 1;

            // Calculate asteroid values
            var radius       = Random.Range(asteroidRadiusMin, asteroidRadiusMax);
            var radius2      = radius / SGT_Helper.InscribedBox;
            var textureCellX = (float)Random.Range(0, asteroidTextureTilesX);
            var textureCellY = (float)Random.Range(0, asteroidTextureTilesY);
            var uvMin        = new Vector2(uvStep.x * textureCellX, uvStep.y * textureCellY);
            var uvMax        = uvStep + uvMin;
            var roll         = Random.Range(-Mathf.PI, Mathf.PI);
            var right        = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, roll);
            var up           = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, roll);
            var angle        = Random.Range(-Mathf.PI, Mathf.PI);
            var distance01   = GenerateDistance01();
            var distance     = SGT_Helper.Remap(0.0f, 1.0f, distance01, ringRadiusInner, ringRadiusOuter);
            var rps          = SGT_Helper.Clamp(Mathf.Lerp(orbitRateInner, orbitRateOuter, distance01) + Random.Range(-orbitRateDeviation, orbitRateDeviation), orbitRateInner, orbitRateOuter);
            var height       = Random.value;
            var spinRate     = Random.value;

            var position = new Vector3(angle, distance, rps);
            var colour   = new Color(height, spinRate, 0.0f);
            var uv1      = new Vector2(radius, radius2);

            // Write star values into vertex data
            positions[vertexIndex + 0] = position;
            positions[vertexIndex + 1] = position;
            positions[vertexIndex + 2] = position;
            positions[vertexIndex + 3] = position;

            colours[vertexIndex + 0] = colour;
            colours[vertexIndex + 1] = colour;
            colours[vertexIndex + 2] = colour;
            colours[vertexIndex + 3] = colour;

            normals[vertexIndex + 0] = SGT_Helper.NewVector3(-right + up, 0.0f);
            normals[vertexIndex + 1] = SGT_Helper.NewVector3(right + up, 0.0f);
            normals[vertexIndex + 2] = SGT_Helper.NewVector3(-right - up, 0.0f);
            normals[vertexIndex + 3] = SGT_Helper.NewVector3(right - up, 0.0f);

            uv0s[vertexIndex + 0] = new Vector2(uvMin.x, uvMax.y);
            uv0s[vertexIndex + 1] = new Vector2(uvMax.x, uvMax.y);
            uv0s[vertexIndex + 2] = new Vector2(uvMin.x, uvMin.y);
            uv0s[vertexIndex + 3] = new Vector2(uvMax.x, uvMin.y);

            uv1s[vertexIndex + 0] = uv1;
            uv1s[vertexIndex + 1] = uv1;
            uv1s[vertexIndex + 2] = uv1;
            uv1s[vertexIndex + 3] = uv1;
        }

        var asteroidMesh = new Mesh();

        asteroidMesh.hideFlags = HideFlags.DontSave;
        asteroidMesh.vertices  = positions;
        asteroidMesh.triangles = indices;
        asteroidMesh.normals   = normals;
        asteroidMesh.colors    = colours;
        asteroidMesh.uv        = uv0s;
        asteroidMesh.uv1       = uv1s;
        asteroidMesh.bounds    = bounds;

        return(asteroidMesh);
    }
    private Mesh GenerateStarMesh(int starCount)
    {
        var positions = new Vector3[starCount * 4];
        var indices   = new int[starCount * 6];
        var uv0s      = new Vector2[starCount * 4];
        var uv1s      = new Vector2[starCount * 4];
        var normals   = new Vector3[starCount * 4];
        var colours   = new Color[starCount * 4];
        var bounds    = new Bounds();
        var weights   = new SGT_WeightedRandom(100);

        for (var i = 0; i < StarVariantCount; i++)
        {
            var ssv = GetStarVariant(i);

            weights.Add(i, ssv != null ? ssv.SpawnProbability : 1.0f);
        }

        for (var i = 0; i < starCount; i++)
        {
            var i0 = i * 6;
            var i1 = i0 + 1;
            var i2 = i1 + 1;
            var i3 = i2 + 1;
            var i4 = i3 + 1;
            var i5 = i4 + 1;

            var v0 = i * 4;
            var v1 = v0 + 1;
            var v2 = v1 + 1;
            var v3 = v2 + 1;

            // Index data
            indices[i0] = v0;
            indices[i1] = v1;
            indices[i2] = v2;
            indices[i3] = v3;
            indices[i4] = v2;
            indices[i5] = v1;

            // Calculate star values
            var position = GeneratePosition();
            var index    = weights.RandomIndex;
            var po       = packer.GetOutput(index);
            var ssv      = GetStarVariant(index);

            float baseRadius, minRadius, maxRadius;

            if (ssv != null && ssv.Custom == true)
            {
                baseRadius = Random.Range(ssv.CustomRadiusMin, ssv.CustomRadiusMax);
                minRadius  = Mathf.Max(baseRadius - ssv.CustomPulseRadiusMax, ssv.CustomRadiusMin);
                maxRadius  = Mathf.Min(baseRadius + ssv.CustomPulseRadiusMax, ssv.CustomRadiusMax);
            }
            else
            {
                baseRadius = Random.Range(starRadiusMin, starRadiusMax);
                minRadius  = Mathf.Max(baseRadius - starPulseRadiusMax, starRadiusMin);
                maxRadius  = Mathf.Min(baseRadius + starPulseRadiusMax, starRadiusMax);
            }

            var midRadius   = (minRadius + maxRadius) * 0.5f;
            var pulseRadius = (maxRadius - minRadius) * 0.5f;
            var pulseRate   = Random.Range(0.0f, 1.0f);
            var pulseOffset = Random.Range(0.0f, 1.0f);

            var colour    = new Color(pulseRate, pulseOffset, 0.0f);
            var uv1       = new Vector2(midRadius, pulseRadius);
            var rollAngle = Random.Range(-Mathf.PI, Mathf.PI);
            var right     = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, rollAngle);
            var up        = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, rollAngle);

            bounds.Encapsulate(position);

            // Write star values into vertex data
            positions[v0] = position;
            positions[v1] = position;
            positions[v2] = position;
            positions[v3] = position;

            normals[v0] = SGT_Helper.NewVector3(-right + up, 0.0f);
            normals[v1] = SGT_Helper.NewVector3(right + up, 0.0f);
            normals[v2] = SGT_Helper.NewVector3(-right - up, 0.0f);
            normals[v3] = SGT_Helper.NewVector3(right - up, 0.0f);

            colours[v0] = colour;
            colours[v1] = colour;
            colours[v2] = colour;
            colours[v3] = colour;

            if (po != null)
            {
                uv0s[v0] = po.UvTopLeft;
                uv0s[v1] = po.UvTopRight;
                uv0s[v2] = po.UvBottomLeft;
                uv0s[v3] = po.UvBottomRight;
            }

            uv1s[v0] = uv1;
            uv1s[v1] = uv1;
            uv1s[v2] = uv1;
            uv1s[v3] = uv1;
        }

        bounds.Expand(starRadiusMax);

        var starMesh = new Mesh();

        starMesh.name      = "Starfield";
        starMesh.bounds    = bounds;
        starMesh.vertices  = positions;
        starMesh.normals   = normals;
        starMesh.colors    = colours;
        starMesh.uv        = uv0s;
        starMesh.uv2       = uv1s;
        starMesh.triangles = indices;

        return(starMesh);
    }
    private Mesh GenerateStarMesh(int starOffset, int starCount)
    {
        var positions = new Vector3[starCount * 4];
        var indices   = new int[starCount * 6];
        var uv0s      = new Vector2[starCount * 4];
        var uv1s      = new Vector2[starCount * 4];
        var normals   = new Vector3[starCount * 4];
        var colours   = new Color[starCount * 4];
        var bounds    = new Bounds();

        for (var i = 0; i < starCount; i++)
        {
            var i0 = i * 6;
            var i1 = i0 + 1;
            var i2 = i1 + 1;
            var i3 = i2 + 1;
            var i4 = i3 + 1;
            var i5 = i4 + 1;

            var v0 = i * 4;
            var v1 = v0 + 1;
            var v2 = v1 + 1;
            var v3 = v2 + 1;

            // Index data
            indices[i0] = v0;
            indices[i1] = v1;
            indices[i2] = v2;
            indices[i3] = v3;
            indices[i4] = v2;
            indices[i5] = v1;

            // Calculate star values
            var starData    = GenerateStar();
            var midRadius   = (starData.RadiusMin + starData.RadiusMax) * 0.5f;
            var pulseRadius = (starData.RadiusMax - starData.RadiusMin) * 0.5f;

            var position = starData.Position;
            var colour   = new Color(starData.RadiusPulseRate, starData.RadiusPulseOffset, 0.0f);
            var uv0      = starData.Variant.Coords;
            var uv1      = new Vector2(midRadius, pulseRadius);
            var right    = SGT_Helper.Rotate(Vector2.right * SGT_Helper.InscribedBox, starData.Angle);
            var up       = SGT_Helper.Rotate(Vector2.up * SGT_Helper.InscribedBox, starData.Angle);

            bounds.Encapsulate(position);

            // Write star values into vertex data
            positions[v0] = position;
            positions[v1] = position;
            positions[v2] = position;
            positions[v3] = position;

            normals[v0] = SGT_Helper.NewVector3(-right + up, 0.0f);
            normals[v1] = SGT_Helper.NewVector3(right + up, 0.0f);
            normals[v2] = SGT_Helper.NewVector3(-right - up, 0.0f);
            normals[v3] = SGT_Helper.NewVector3(right - up, 0.0f);

            colours[v0] = colour;
            colours[v1] = colour;
            colours[v2] = colour;
            colours[v3] = colour;

            uv0s[v0] = uv0[0];
            uv0s[v1] = uv0[1];
            uv0s[v2] = uv0[2];
            uv0s[v3] = uv0[3];

            uv1s[v0] = uv1;
            uv1s[v1] = uv1;
            uv1s[v2] = uv1;
            uv1s[v3] = uv1;
        }

        bounds.Expand(starRadiusMax);

        var starMesh = new Mesh();

        starMesh.hideFlags = HideFlags.DontSave;
        starMesh.name      = "Starfield";
        starMesh.bounds    = bounds;
        starMesh.vertices  = positions;
        starMesh.normals   = normals;
        starMesh.colors    = colours;
        starMesh.uv        = uv0s;
        starMesh.uv1       = uv1s;
        starMesh.triangles = indices;

        return(starMesh);
    }