示例#1
0
        // perlin -- Calculate perlin noise
        // reference: "Simplex Noise Demystified" http://webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
        private float perlin(
            Vector2[,] grid,
            int gridWidth,
            int gridHeight,
            Vector2 position)
        {
            int X = (int)Math.Floor(position.X);
            int Y = (int)Math.Floor(position.Y);

            // Get relative xy coordinates of point within that cell
            float x = position.X - X;
            float y = position.Y - Y;

            // Wrap the integer cells
            int x0 = StasisMathHelper.mod(X, gridWidth);
            int x1 = StasisMathHelper.mod(X + 1, gridWidth);
            int y0 = StasisMathHelper.mod(Y, gridHeight);
            int y1 = StasisMathHelper.mod(Y + 1, gridHeight);

            // Get gradients
            Vector2 g00 = grid[x0, y0];
            Vector2 g10 = grid[x1, y0];
            Vector2 g01 = grid[x0, y1];
            Vector2 g11 = grid[x1, y1];

            // Calculate noise contributions from each of the eight corners
            float n00 = Vector2.Dot(g00, new Vector2(x, y));
            float n10 = Vector2.Dot(g10, new Vector2(x - 1, y));
            float n01 = Vector2.Dot(g01, new Vector2(x, y - 1));
            float n11 = Vector2.Dot(g11, new Vector2(x - 1, y - 1));

            // Compute the fade curve value for each of x, y, z
            float u = perlinWeight(x);
            float v = perlinWeight(y);

            // Interpolate along x the contributions from each of the corners
            float nx00 = MathHelper.Lerp(n00, n10, u);
            float nx10 = MathHelper.Lerp(n01, n11, u);

            // Interpolate the results along y
            float value = MathHelper.Lerp(nx00, nx10, v);

            return(value);
        }
示例#2
0
        // Edge scatter pass
        public Texture2D edgeScatterPass(
            Texture2D current,
            List <Vector2> polygonPoints,
            List <string> textureUIDs,
            Vector2 direction,
            float threshold,
            bool hardCutoff,
            float spacing,
            bool useAbsoluteAngle,
            float absoluteAngle,
            float relativeAngle,
            float angleJitter,
            float jitter,
            float scale,
            float scaleJitter,
            Color baseColor,
            int randomRed,
            int randomGreen,
            int randomBlue,
            int randomAlpha)
        {
            Random rng = new Random();

            // Initialize render targets and textures
            RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, current.Width, current.Height);
            Texture2D      result       = new Texture2D(_graphicsDevice, renderTarget.Width, renderTarget.Height);

            Color[] data = new Color[renderTarget.Width * renderTarget.Height];

            // Load and validate textures
            List <Texture2D> textures = new List <Texture2D>();

            foreach (string textureUID in textureUIDs)
            {
                Texture2D texture = ResourceManager.getTexture(textureUID);
                if (texture == null)
                {
                    return(result);
                }
                textures.Add(texture);
            }
            if (textures.Count == 0)
            {
                return(current);
            }

            // Validate polygon points
            if (polygonPoints == null || polygonPoints.Count < 3)
            {
                return(current);
            }

            // Validate parameters
            spacing = Math.Max(0.05f, spacing);

            // Calculate half-texture offset
            Vector2 topLeft     = polygonPoints[0];
            Vector2 bottomRight = polygonPoints[0];

            for (int i = 0; i < polygonPoints.Count; i++)
            {
                topLeft     = Vector2.Min(polygonPoints[i], topLeft);
                bottomRight = Vector2.Max(polygonPoints[i], bottomRight);
            }

            // Draw
            _graphicsDevice.SetRenderTarget(renderTarget);
            _graphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            _spriteBatch.Draw(current, current.Bounds, Color.White);
            bool hasDirection = direction.X != 0 || direction.Y != 0;

            for (int i = 0; i < polygonPoints.Count; i++)
            {
                Vector2 pointA   = polygonPoints[i];
                Vector2 pointB   = polygonPoints[i == polygonPoints.Count - 1 ? 0 : i + 1];
                Vector2 relative = pointB - pointA;
                Vector2 normal   = relative;
                float   perpDot  = 0;
                normal.Normalize();
                if (hasDirection)
                {
                    direction.Normalize();
                    perpDot = direction.X * normal.Y - direction.Y * normal.X;
                }
                if (!hasDirection || perpDot > -threshold)
                {
                    float relativeLength  = relative.Length();
                    float currentPosition = 0f;
                    while (currentPosition < relativeLength)
                    {
                        float     angle        = 0;
                        Vector2   j            = new Vector2((float)rng.NextDouble() * 2 - 1, (float)rng.NextDouble() * 2 - 1) * jitter;
                        Vector2   position     = pointA + normal * currentPosition + j;
                        Texture2D texture      = textures[rng.Next(textures.Count)];
                        Color     actualColor  = getRandomColor(baseColor, randomRed, randomGreen, randomBlue, randomAlpha, rng);
                        float     textureScale = StasisMathHelper.floatBetween(scale - scaleJitter, scale + scaleJitter, rng);

                        if (useAbsoluteAngle)
                        {
                            angle = absoluteAngle + StasisMathHelper.floatBetween(-angleJitter, angleJitter, rng);
                        }
                        else
                        {
                            angle = (float)Math.Atan2(relative.Y, relative.X) + relativeAngle + StasisMathHelper.floatBetween(-angleJitter, angleJitter, rng);
                        }
                        _spriteBatch.Draw(texture, (position - topLeft) * Settings.BASE_SCALE, texture.Bounds, actualColor, angle, new Vector2(texture.Width, texture.Height) / 2, textureScale, SpriteEffects.None, 0);
                        currentPosition += spacing;
                    }
                }
            }
            _spriteBatch.End();
            _graphicsDevice.SetRenderTarget(null);

            // Save render target into texture
            renderTarget.GetData <Color>(data);
            result.SetData <Color>(data);

            // Cleanup
            renderTarget.Dispose();

            return(result);
        }
示例#3
0
        // Radial scatter pass
        public Texture2D radialScatterPass(
            Texture2D current,
            float growthFactor,
            List <string> textureUIDs,
            bool scaleWithGrowthFactor,
            float a,
            float b,
            float intersections,
            float maxRadius,
            int arms,
            bool twinArms,
            bool flipArms,
            bool useAbsoluteTextureAngle,
            float absoluteTextureAngle,
            float relativeTextureAngle,
            float textureAngleJitter,
            float jitter,
            float centerJitter,
            Vector2 centerOffset,
            Color baseColor,
            float minTextureScale,
            float maxTextureScale,
            int randomRed,
            int randomGreen,
            int randomBlue,
            int randomAlpha)
        {
            Random rng = new Random();

            // Initialize render targets and textures
            RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, current.Width, current.Height);
            Texture2D      result       = new Texture2D(_graphicsDevice, renderTarget.Width, renderTarget.Height);

            Color[] data = new Color[renderTarget.Width * renderTarget.Height];

            // Load and validate textures
            List <Texture2D> textures = new List <Texture2D>();

            foreach (string textureUID in textureUIDs)
            {
                Texture2D texture = ResourceManager.getTexture(textureUID);
                if (texture == null)
                {
                    return(result);
                }
                textures.Add(texture);
            }
            if (textures.Count == 0)
            {
                return(current);
            }

            // Modify parameters based on growth factor (r is modified later)
            intersections *= growthFactor * growthFactor * growthFactor;
            arms           = (int)Math.Ceiling(arms * growthFactor * growthFactor);
            maxRadius     *= growthFactor;
            jitter        *= Math.Max(growthFactor, 0.1f);
            centerJitter  *= growthFactor;
            centerOffset  *= growthFactor;

            // Draw
            _graphicsDevice.SetRenderTarget(renderTarget);
            _graphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            _spriteBatch.Draw(current, current.Bounds, Color.White);
            float   thetaIncrement       = StasisMathHelper.pi * 2 / intersections;
            float   armRotationIncrement = StasisMathHelper.pi * 2 / (float)arms;
            Vector2 center = centerOffset + new Vector2(current.Width, current.Height) / 2 + new Vector2((float)(rng.NextDouble() * 2 - 1), (float)(rng.NextDouble() * 2 - 1)) * centerJitter;

            for (int i = 0; i < arms; i++)
            {
                float theta = 0;
                float r     = 0;
                while (r < maxRadius)
                {
                    r = a * (float)Math.Pow(StasisMathHelper.phi, b * (2f / StasisMathHelper.pi) * theta) * growthFactor;
                    if (r < maxRadius)
                    {
                        float textureScale     = StasisMathHelper.floatBetween(minTextureScale, maxTextureScale, rng);
                        float modifiedTheta    = (theta + armRotationIncrement * i) * (flipArms ? -1f : 1f);
                        float randomAngleValue = textureAngleJitter == 0 ? 0 : StasisMathHelper.floatBetween(-textureAngleJitter, textureAngleJitter, rng);
                        float textureAngle;
                        if (useAbsoluteTextureAngle)
                        {
                            textureAngle = absoluteTextureAngle + randomAngleValue;
                        }
                        else
                        {
                            textureAngle = relativeTextureAngle + modifiedTheta + randomAngleValue;
                        }
                        Vector2   j           = new Vector2((float)(rng.NextDouble() * 2 - 1) * jitter, (float)(rng.NextDouble() * 2 - 1) * jitter);
                        Texture2D texture     = textures[rng.Next(textures.Count)];
                        Color     actualColor = getRandomColor(baseColor, randomRed, randomGreen, randomBlue, randomAlpha, rng);
                        //float textureScale = scaleWithGrowthFactor ? growthFactor : 1f;
                        _spriteBatch.Draw(texture, new Vector2(r * (float)Math.Cos(modifiedTheta), r * (float)Math.Sin(modifiedTheta)) + j + center, texture.Bounds, actualColor, textureAngle, new Vector2(texture.Width, texture.Height) / 2, textureScale, SpriteEffects.None, 0);
                        if (twinArms)
                        {
                            j = new Vector2((float)(rng.NextDouble() * 2 - 1) * jitter, (float)(rng.NextDouble() * 2 - 1) * jitter);
                            _spriteBatch.Draw(texture, new Vector2(r * (float)Math.Cos(-modifiedTheta), r * (float)Math.Sin(-modifiedTheta)) + j + center, texture.Bounds, actualColor, -textureAngle, new Vector2(texture.Width, texture.Height) / 2, textureScale, SpriteEffects.None, 0);
                        }
                    }
                    theta += thetaIncrement;
                }
            }
            _spriteBatch.End();
            _graphicsDevice.SetRenderTarget(null);

            // Save render target into texture
            renderTarget.GetData <Color>(data);
            result.SetData <Color>(data);

            // Cleanup
            renderTarget.Dispose();

            return(result);
        }
示例#4
0
        // Uniform scatter pass
        public Texture2D uniformScatterPass(
            Texture2D current,
            List <string> textureUIDs,
            float horizontalSpacing,
            float verticalSpacing,
            float jitter,
            Color baseColor,
            int randomRed,
            int randomGreen,
            int randomBlue,
            int randomAlpha)
        {
            Random rng = new Random();

            // Initialize render targets and textures
            RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, current.Width, current.Height);
            Texture2D      result       = new Texture2D(_graphicsDevice, renderTarget.Width, renderTarget.Height);

            Color[] data = new Color[renderTarget.Width * renderTarget.Height];

            // Load and validate textures
            List <Texture2D> textures = new List <Texture2D>();

            foreach (string textureUID in textureUIDs)
            {
                Texture2D texture = ResourceManager.getTexture(textureUID);
                if (texture == null)
                {
                    return(result);
                }
                textures.Add(texture);
            }
            if (textures.Count == 0)
            {
                return(current);
            }

            // Draw
            _graphicsDevice.SetRenderTarget(renderTarget);
            _graphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            _spriteBatch.Draw(current, current.Bounds, Color.White);
            for (float i = 0; i <= current.Width; i += horizontalSpacing)
            {
                for (float j = 0; j <= current.Height; j += verticalSpacing)
                {
                    Vector2   position    = new Vector2(i, j) + new Vector2(StasisMathHelper.floatBetween(0, jitter, rng), StasisMathHelper.floatBetween(0, jitter, rng));
                    float     angle       = StasisMathHelper.floatBetween(-3.14f, 3.14f, rng);
                    Texture2D texture     = textures[rng.Next(0, textures.Count)];
                    Color     actualColor = getRandomColor(baseColor, randomRed, randomGreen, randomBlue, randomAlpha, rng);
                    _spriteBatch.Draw(texture, position, texture.Bounds, actualColor, angle, new Vector2(texture.Width, texture.Height) / 2, 1f, SpriteEffects.None, 0);
                }
            }
            _spriteBatch.End();
            _graphicsDevice.SetRenderTarget(null);

            // Save render target into texture
            renderTarget.GetData <Color>(data);
            result.SetData <Color>(data);

            // Cleanup
            renderTarget.Dispose();

            return(result);
        }
示例#5
0
        // Worley noise pass
        public Texture2D worleyPass(
            Texture2D current,
            int seed,
            Vector2 position,
            float scale,
            float frequency,
            float gain,
            float lacunarity,
            float multiplier,
            Vector2 fbmOffset,
            Color colorLow,
            Color colorHigh,
            int iterations,
            WorleyFeatureType worleyFeatureType,
            bool invert)
        {
            Texture2D output = new Texture2D(_graphicsDevice, current.Width, current.Height);

            Color[] data       = new Color[output.Width * output.Height];
            int     gridWidth  = 32;
            int     gridHeight = 32;

            Vector2[,] grid = new Vector2[gridWidth, gridHeight];
            Random rng        = new Random(seed);
            int    chunkCount = (int)Math.Floor((float)output.Width / (float)CHUNK_SIZE) + 1;

            // Create gradient grid
            for (int i = 0; i < gridWidth; i++)
            {
                for (int j = 0; j < gridHeight; j++)
                {
                    grid[i, j] = new Vector2(
                        StasisMathHelper.floatBetween(-1, 1, rng),
                        StasisMathHelper.floatBetween(-1, 1, rng));
                }
            }

            Parallel.For(0, chunkCount, (count) =>
            {
                int startIndex = count * CHUNK_SIZE;
                int endIndex   = Math.Min((count + 1) * CHUNK_SIZE, output.Width);
                for (int i = startIndex; i < endIndex; i++)
                {
                    for (int j = 0; j < output.Height; j++)
                    {
                        Vector2 p = new Vector2(i, j) / new Vector2(gridWidth, gridHeight);
                        p        += position;
                        p        /= scale;

                        float value = fbmWorley(
                            grid,
                            gridWidth,
                            gridHeight,
                            p,
                            frequency,
                            gain,
                            lacunarity,
                            fbmOffset,
                            iterations,
                            worleyFeatureType);

                        // Clamp values
                        value = Math.Max(0, Math.Min(1, value));

                        // Multiply value
                        value *= multiplier;

                        // Invert value if necessary
                        if (invert)
                        {
                            value = 1 - value;
                        }

                        Color color = Color.Lerp(colorLow, colorHigh, value);
                        data[i + j * output.Width] = color;
                    }
                }
            });

            output.SetData <Color>(data);
            return(output);
        }
示例#6
0
        // Leaves pass
        public Texture2D leavesPass(
            Texture2D current,
            float growthFactor,
            List <string> textureUids,
            Color baseColor
            )
        {
            // Initialize render targets and textures
            RenderTarget2D renderTarget = new RenderTarget2D(_graphicsDevice, current.Width, current.Height);
            Texture2D      result       = new Texture2D(_graphicsDevice, renderTarget.Width, renderTarget.Height);

            Color[] data = new Color[renderTarget.Width * renderTarget.Height];
            Random  rng  = new Random();

            // Load and validate textures
            List <Texture2D> textures = new List <Texture2D>();

            foreach (string textureUID in textureUids)
            {
                Texture2D texture = ResourceManager.getTexture(textureUID);
                if (texture == null)
                {
                    return(result);
                }
                textures.Add(texture);
            }
            if (textures.Count == 0)
            {
                return(current);
            }

            float maxTextureSize = 256;
            float size           = maxTextureSize * growthFactor;
            float maxRadius      = (size / 2f) * 0.85f;
            float lowTint        = 0.3f;

            if (size < 48f)
            {
                return(current);
            }

            // Draw
            _graphicsDevice.SetRenderTarget(renderTarget);
            _graphicsDevice.Clear(Color.Transparent);
            _spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend);
            _spriteBatch.Draw(current, current.Bounds, Color.White);
            for (float tint = lowTint; tint < 1f; tint += 0.1f)
            {
                float radius    = maxRadius * (1f - tint + lowTint);
                int   leafCount = (int)((radius / 2f) * (size / maxTextureSize));
                //Console.WriteLine("maxTextureSize: {0}, size: {1}, maxRadius: {2}, radius: {3}, tint: {4}, leafCount: {5}", maxTextureSize, size, maxRadius, radius, tint, leafCount);
                for (int n = 0; n < leafCount; n++)
                {
                    // Calculate random position
                    Texture2D leafTexture = textures[rng.Next(textures.Count)];
                    Vector2   position    = new Vector2(StasisMathHelper.floatBetween(-1f, 1f, rng), StasisMathHelper.floatBetween(-1f, 1f, rng)) * radius;
                    position += new Vector2(current.Width, current.Height) / 2;

                    // Calculate shadow value
                    //float shadowValue = Math.Max(metamer.budQuality, 0.5f);

                    // Calculate color value
                    float r          = StasisMathHelper.floatBetween(0.9f, 1.2f, rng);
                    float g          = StasisMathHelper.floatBetween(0.9f, 1.1f, rng);
                    float b          = StasisMathHelper.floatBetween(0.9f, 1f, rng);
                    Color finalColor = new Color(tint * r * (baseColor.R / 255f), tint * g * (baseColor.G / 255f), tint * b * (baseColor.B / 255f));

                    float angle = (float)(rng.NextDouble() * Math.PI * 2);
                    float scale = StasisMathHelper.floatBetween(0.25f, 1f, rng);
                    _spriteBatch.Draw(leafTexture, position, leafTexture.Bounds, finalColor, angle, new Vector2(leafTexture.Width, leafTexture.Height) / 2, scale, SpriteEffects.None, 0);
                }
            }
            _spriteBatch.End();
            _graphicsDevice.SetRenderTarget(null);

            // Save render target into texture
            renderTarget.GetData <Color>(data);
            result.SetData <Color>(data);

            // Cleanup
            renderTarget.Dispose();

            return(result);
        }