一、前言
程序纹理就是指由计算机生成的图像,我们可以通过各种参数来控制纹理的外观,这些属性不仅仅是颜色属性,还可以是完全不同类型的图案属性,可以使我们得到更丰富的动画和视觉效果。
二、实现程序纹理
简单思想:先创建一个材质,然后给它使用之前学过的单张纹理Shader,因为我们没有纹理,所以在应用材质的模型身上挂载脚本-程序纹理来进行创建赋值。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
[ExecuteInEditMode] //允许代码在编辑器模式下运行
public class ProceduralTextureGeneration : MonoBehaviour {
public Material material = null; //声明材质
#region Material properties
[SerializeField, SetProperty("textureWidth")] //设置属性 大小
private int m_textureWidth = 512;
public int textureWidth {
get {
return m_textureWidth;
}
set {
m_textureWidth = value;
_UpdateMaterial();
}
}
[SerializeField, SetProperty("backgroundColor")] //背景颜色
private Color m_backgroundColor = Color.white;
public Color backgroundColor {
get {
return m_backgroundColor;
}
set {
m_backgroundColor = value;
_UpdateMaterial();
}
}
[SerializeField, SetProperty("circleColor")] //圆点颜色、
private Color m_circleColor = Color.yellow;
public Color circleColor {
get {
return m_circleColor;
}
set {
m_circleColor = value;
_UpdateMaterial();
}
}
[SerializeField, SetProperty("blurFactor")] //模糊因子(用来模糊圆形边界)
private float m_blurFactor = 2.0f;
public float blurFactor {
get {
return m_blurFactor;
}
set {
m_blurFactor = value;
_UpdateMaterial();
}
}
#endregion
private Texture2D m_generatedTexture = null; //声明一个Texture2D纹理变量
// Use this for initialization
void Start () {
if (material == null) { //进行材质和render组件判断并使用
Renderer renderer = gameObject.GetComponent<Renderer>();
if (renderer == null) {
Debug.LogWarning("Cannot find a renderer.");
return;
}
material = renderer.sharedMaterial; //从物体组件上获取材质
}
_UpdateMaterial();
}
private void _UpdateMaterial() { //这个函数可以在修改属性时进行更新纹理
if (material != null) {
m_generatedTexture = _GenerateProceduralTexture(); //函数用于生成程序纹理
material.SetTexture("_MainTex", m_generatedTexture); //材质中有_MainTex,将程序纹理赋值
}
}
private Color _MixColor(Color color0, Color color1, float mixFactor) {
Color mixColor = Color.white;
mixColor.r = Mathf.Lerp(color0.r, color1.r, mixFactor);
mixColor.g = Mathf.Lerp(color0.g, color1.g, mixFactor);
mixColor.b = Mathf.Lerp(color0.b, color1.b, mixFactor);
mixColor.a = Mathf.Lerp(color0.a, color1.a, mixFactor);
return mixColor;
}
private Texture2D _GenerateProceduralTexture() {
Texture2D proceduralTexture = new Texture2D(textureWidth, textureWidth); //初始化一个2D纹理,
float circleInterval = textureWidth / 4.0f; //设置圆圈间距
float radius = textureWidth / 10.0f; //定义圆半径
float edgeBlur = 1.0f / blurFactor; //定义模糊系数
for (int w = 0; w < textureWidth; w++) { //两个for循环,循环遍历每个像素。
for (int h = 0; h < textureWidth; h++) {
Color pixel = backgroundColor; //背景颜色像素
for (int i = 0; i < 3; i++) { //两个for循环用来画圆更新圆的像素颜色
for (int j = 0; j < 3; j++) {
Vector2 circleCenter = new Vector2(circleInterval * (i + 1), circleInterval * (j + 1)); //找到圆心
float dist = Vector2.Distance(new Vector2(w, h), circleCenter) - radius; //计算当前像素和圆心之间的像素
Color color = _MixColor(circleColor, new Color(pixel.r, pixel.g, pixel.b, 0.0f), Mathf.SmoothStep(0f, 1.0f, dist * edgeBlur)); //将像素源颜色和圆的颜色混合
pixel = _MixColor(pixel, color, color.a); //更新像素颜色
}
}
proceduralTexture.SetPixel(w, h, pixel); //设置纹理颜色
}
}
proceduralTexture.Apply(); //强制写入纹理
return proceduralTexture; //返回程序纹理
}
}
三、Unity的程序材质
Unity的程序材质是一种专门使用程序纹理的,它和正常材质本质上一样,不同就在于它使用程序纹理,这个材质不是在Unity中创建的,它是通过一个外面的软件 Substance Designer ,在外部生成的。
Substance Designer是一个非常出色的纹理生成工具,很多3A游戏都有使用它来生成材质,在资源商店可以获取很多Substance的后缀为.sbsar的材质。
这些材质导入Unity后会生成一个程序纹理资源,这些程序纹理资源可以包含一个或多个程序材质,每个程序纹理会使用不同的参数,Unity也会为他们生成不同的程序纹理。
程序纹理强大在于它们的多变性,自由度高。