I’m pretty new to this, and anything relating to textures/sprites/particles/whatever I really haven’t wrapped my head around yet, so bear with me.
I’m trying to create a quad that displays a white noise visual effect, by going through each pixel and randomly setting them to either black or white each new frame, but I really don’t know how to go about doing this, how do I change the pixels of the sprite/texture (what’s the difference?) and then apply that as a new sprite/texture?
Here’s the code I’m using, which is executing but not having any affect.
using UnityEngine;
using System.Collections;
public class WhiteNoiseController : MonoBehaviour
{
void Start()
{
Texture2D texture = new Texture2D(128, 128);
GetComponent<Renderer>().material.mainTexture = texture;
for (int y = 0; y < texture.height; y++)
{
for (int x = 0; x < texture.width; x++) //Goes through each pixel
{
Color pixelColour;
if (Random.Range(0, 2) == 1 ) //50/50 chance it will be black or white
{
pixelColour = new Color(0, 0, 0, 1);
}
else
{
pixelColour = new Color(1, 1, 1, 1);
}
texture.SetPixel(x, y, pixelColour);
}
}
Debug.Log("Texture applied");
texture.Apply();
}
}
Sprites are objects in unity to encapsulate drawing 2D images. And one of the properties of a Sprite is its texture. it is this texture that is what is used
Now you can’t directly set a texture of an existing sprite, its read only. You can create your own texture, and then create a sprite from that, and set that sprite to the sprite of the Sprite Renderer like this:
void Start()
{
Texture2D texture = new Texture2D(128, 128);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 128, 128), Vector2.zero);
GetComponent<SpriteRenderer>().sprite = sprite;
for (int y = 0; y < texture.height; y++)
{
for (int x = 0; x < texture.width; x++) //Goes through each pixel
{
Color pixelColour;
if (Random.Range(0, 2) == 1) //50/50 chance it will be black or white
{
pixelColour = new Color(0, 0, 0, 1);
}
else
{
pixelColour = new Color(1, 1, 1, 1);
}
texture.SetPixel(x, y, pixelColour);
}
}
texture.Apply();
Now the mainTexture of the material is used by the shader. The actual color Values of the material are not used in the default SpriteShaders, but the alpha value of the color of this material is used. The Tint Color of this material is also used to modify the color values of your Sprite. Other Shader’s use the color value of the materia’s mainTexture. In fact that is how 3D objects are colored.
Edit: Just tested and the alpha values of the mainTexture are also not used by the Sprite Shaders… its purely the color and alpha of the tint Value you set that is used. You could write your own Sprite Shader that used the material’s mainTexture for information, but currently the SpriteShaders ignore the material’s texture all together
One last thing though, for the quad to cover the size of the area I need I must use “1024” for the values on the first two lines, not “128”, obviously performing 1024^2 calculations each frame update isn’t exactly feasible, is there a way to optimize this? say have a lower number of pixels for a texture of a certain size?
Never mind, found a way around this by setting a block of 4 pixels to black or white, not each individual pixel…
void Update()
{
Texture2D texture = new Texture2D(413, 715);
Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 413, 715), Vector2.zero);
GetComponent<SpriteRenderer>().sprite = sprite;
for (int y = 0; y < texture.height; y = y + 2)
{
for (int x = 0; x < texture.width; x = x + 2) //Goes through each 2 x 2 block of pixels
{
Color pixelColour;
if (Random.Range(0, 2) == 1) //50/50 chance it will be black or white
{
pixelColour = new Color(0, 0, 0, 1); //Black
}
else
{
pixelColour = new Color(1, 1, 1, 1); //White
}
texture.SetPixel(x, y, pixelColour);
texture.SetPixel(x + 1, y, pixelColour);
texture.SetPixel(x, y + 1, pixelColour);
texture.SetPixel(x + 1, y + 1, pixelColour);
//Setting each pixel is too CPU hungry - so set them in blocks of 4
}
}
texture.Apply();
}