How do I create a Radial Gradient Texture Mask using code ._.

I know I could very easily whip one up in Photoshop in two seconds, BUT, I have set myself a challenge of creating EVERYTHING in this project by pure code. Essentially I need it for masking run-time generated noise via add/subtract/multiply for different effects. I’ve searched everywhere and the only solution I found was a very abstract application in a language I didn’t even recognize. I know there is probably a very simple solution to this but it’s one of those brain blocking problems I just can’t seem to fathom out on my own.

I would have thought it was a simple matter of setting the pixel RGB’s based upon the X Y index locations of each pixel location (linear gradient) but after further reading I have seen people use Mathf.PI and Mathf.Sin. I understand these concepts individually but have no idea how they come together to create this…

It would be fantastic if we could come up with a coded solution for this for everybody, it has lots of applications for people looking to create games procedurally.

18861-radial_gradient.png

If what I am guessing is correct, this should be fairly easy. Actually I have a concept that MIGHT work but havent actually tried it.

You need to create a Texture2D and manually set the pixels for it (link!) .

Texture2D tex;

tex = new Texture2D(WIDTH,HEIGHT);

In trignometry every point on the circumference of a circle can be represented as (cos(A)*RADIUS, sin(A)*RADIUS) Where A is the angle from the center of the circle and RADIUS is the radius of the circle. (Though this formula has absolutely nothing to do with what you want!! This explained the formula because u brought it up.
Well there are places this formula would be useful but here you can do it in a lot simpler way.)

Here center point is going to be the center of the Image, and we have to assume that every point in the texture is on a imaginary circle of certain radius. This pic should be more explainatory.

We are going to reduce the alpha as the radius increases. The radius of the circle can be found by finding distance between center of the image and the point.

the idea is to reduce the alpha every certain distance from center gradually. if the distance is 0 which is center, the alpha value should be 1, and as the distance increases, it should end up at 0 alpha (MAX_POSSIBLE_RADIUS , probably the width of the image)

currentAlpha =  (1- (DistanceFromCenter/MAX_POSSIBLE_RADIUS))>=0 ?(1- (DistanceFromCenter/MAX_POSSIBLE_RADIUS) )?0;

When the distance is 0, the alpha will be max at center and 0 at the max distance (note that if the alpha is negative, im settin it to 0.)

Programatically you have to traverse through every pixel, find the distance from center and set the current alpha with above calculation.

Texture2D tex;

tex = new Texture2D(WIDTH,HEIGHT);

Vector2 center = new Vector2( (int) WIDTH/2f,(int) HEIGHT/2f );
for(int i=0;i<WIDTH;i++)
{
     for(int j=0; j< HEIGHT;j++)
     {
         float DistanceFromCenter = Vector2.Distance( center , new Vector2(i,j) );

         currentAlpha =  (1- (DistanceFromCenter/MAX_POSSIBLE_RADIUS))>=0 ?(1- (DistanceFromCenter/MAX_POSSIBLE_RADIUS) )?0;

         Color myColr = new Color(1,1,1,currentAlpha);

         tex.SetPixel(x,y,myColor);
     }
}

this is the concept i have in mind and shd work 90%. PS: This is an untested code, i wrote it just for the reference.

Hope it helps.

You were almost there!! Works wonderfully, what a beautifully simple solution. Here is my implementation of your theory…

//TEXTURE SETTINGS
var texWidth : int = 512;
var texHeight : int = 512;

//MASK SETTINGS
var maskThreshold : float = 2.0;

//REFERENCES
var mask : Texture2D;

function Start(){
	GenerateTexture();	
}

function GenerateTexture(){

    mask = new Texture2D(texWidth, texHeight, TextureFormat.RGBA32, true);
    var maskCenter : Vector2 = new Vector2(texWidth * 0.5, texHeight * 0.5);
   	
    for(var y : int = 0; y < texture.height; ++y){
        for(var x : int = 0; x < texture.width; ++x){

			var distFromCenter : float = Vector2.Distance(maskCenter, new Vector2(x, y));
			var maskPixel : float = (0.5 - (distFromCenter / texWidth)) * maskThreshold;
			mask.SetPixel(x, y, Color(maskPixel, maskPixel, maskPixel, 1.0));
        }
    }
    mask.Apply();
}

I added a threshold variable to control how “sharp” the gradient is which could be useful for randomisation!

I know I’m necroing the crap out of this post. But I stumbled onto it and it helped a lot so I wanted to put up a code snippet that is complete.

public class CreateTexture : MonoBehaviour
{
	public TextureSize textureSize = TextureSize.bit256;
	public enum TextureSize
	{
		bit16 = 16,
		bit32 = 32,
		bit64 = 64,
		bit128 = 128,
		bit256 = 256,
		bit512 = 512,
	}
	public TextureWrapMode wrapMode = TextureWrapMode.Clamp;
	public FilterMode filterMode = FilterMode.Bilinear;

	public void GenerateTexture(int size , FilterMode filter, TextureWrapMode wrap)
	{
		Texture2D texture = new Texture2D(size, size);
		GetComponent<Renderer>().material.mainTexture = texture;

		Vector2 center = new Vector2(size / 2f, size / 2f);

		for (int y = 0; y < texture.height; y++)
		{
			for (int x = 0; x < texture.width; x++)
			{
				float DistanceFromCenter = Vector2.Distance(center, new Vector2(x, y));
				float currentAlpha = 1;

				if((1 - (DistanceFromCenter / size)) >= 0)
				{
					currentAlpha = (1 - (DistanceFromCenter / size));
                }
				else
				{
					currentAlpha = 0;
				}

				Color color = new Color(currentAlpha, currentAlpha, currentAlpha, currentAlpha);
				texture.SetPixel(x, y, color);
			}
		}
		texture.Apply();
		texture.filterMode = filterMode;

		SpriteRenderer s = GetComponent<SpriteRenderer>();
		s.sprite = Sprite.Create(texture,new Rect(0,0,texture.width,texture.height),new Vector2(.5f,.5f));
		s.sprite.name = "New Sprite";	
	}
}

Then I also made a little editor script to keep things pretty… (and working in editor)
70126-capture.jpg

[CanEditMultipleObjects, CustomEditor(typeof(CreateTexture))]
public class CreateTextureInspector : Editor
{
	CreateTexture myTarget;

	public void OnEnable()
	{
		myTarget = (CreateTexture)target;
	}

	public override void OnInspectorGUI()
	{
		DrawDefaultInspector();

		if (GUILayout.Button("New Texture"))
		{
			myTarget.GenerateTexture((int)myTarget.textureSize, myTarget.filterMode, myTarget.wrapMode);
		}
	}
}

Thanks a lot guys :slight_smile: