- Home /
How to apply a generated texture to a mesh?
I'm trying to render a randomly generated texture.
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class RandomTexture : MonoBehaviour {
void Start () {
BuildQuad();
BuildTexture();
}
void BuildTexture() {
Texture2D texture = new Texture2D(16, 16, TextureFormat.RGBA32, false);
// fill texture with random color
for (int x = 0; x < texture.width; x++) {
for (int y = 0; y < texture.height; y++) {
texture.SetPixel(x, y, Random.Range(0, 2) == 0 ? Color.red : Color.blue);
}
}
texture.Apply();
// create a material holding the texture
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
Material material = new Material(Shader.Find("Sprites/Default"));
material.color = Color.white;
material.SetTexture("texture", texture);
// apply material to mesh
meshRenderer.sharedMaterial = material;
renderer.material.mainTexture = texture;
}
void BuildQuad() {
Mesh mesh = new Mesh();
// [...]
// create vertices, triangles, normals and uv for a single quad
MeshFilter meshFilter = GetComponent<MeshFilter>();
meshFilter.mesh = mesh;
}
}
At the end of the BuildTexture
method there are two statements that I don't understand.
If I remove
meshRenderer.sharedMaterial = material
the quad is not rendered at all (or is invisible).If I remove
renderer.material.mainTexture = texture
the quad is rendered completely white.If I keep both lines the quad is rendered as expected.
What is the difference between the two statements? To me it looks like one or the other should be enough. Or is there a better way to do this that I'm missing?
Answer by supernat · May 12, 2014 at 03:20 PM
There is maybe a confusion due to the name of your local variable. As you know, all MonoBehaviour scripts are derived from the Component class, and that class contains properties to let you access standard components on the game object (like renderer, material, gameObject, collider, etc). Since you named your local variable "Material material", it might seem confusing to you, because you are changing the material and expect it to be applied to the current game object. Really you are just creating an object "material" locally that is not applied to anything yet. That is why you have to say "meshRenderer.sharedMaterial = material". In fact, although I don't have the full details, I suspect you can just say "renderer.sharedMaterial = material" instead.
So, another common question is why use renderer.sharedMaterial versus renderer.material, and that is dependent on your need. sharedMaterial is the material that is shared between all game objects that use this material, so to update the texture on all game objects, you would say "renderer.sharedMaterial.mainTexture" but to update only this object "renderer.material.mainTexture".
Your second question is probably due to the SetTexture() call. Unless you've renamed your texture in your shader, you probably meant SetTexture("_MainTex", texture); See this: http://docs.unity3d.com/Documentation/ScriptReference/Material.SetTexture.html Basically your SetTexture call is doing nothing, because it can't find "texture". That's why you have to set it via renderer.material.mainTexture (which actually is the preferred way for the main texture I think).
I think it was indeed the SetTexture
call that got me confused, correcting that it's much easier to understand what the other assignments do. [Edit] Sadly, I cannot upvote your answer.
That's okay, no upvotes needed, just glad I can provide an answer, hopefully it will help someone down the line too (so thanks for marking it answered).
Your answer
