UnityShader之创建动态纹理

接下来要做个塔防游戏,虽然网上有好多好多的塔防插件以及塔防现成的游戏项目,但是我只是想练练手而已, 没想做的多完美,所以不会使用任何插件和特效,会使用引擎内置的资源以及自己的shader

ok,本节 来实现创建动态纹理,顾名思义,在程序的运行期间,如果我们想要修改纹理的像素值或者是其他的数据,那么我们就需要创建一个新的纹理传入到着色器当中,而且这个新的纹理必须拥有一组新的像素。

在场景中新建个GameObject,再新建个C#Script,将脚本拖拽到游戏对象上,接下来编辑脚本。

这里有个预编译指令,简单介绍下,unity内置的预处理指令大家可以搜索下,这里的#region指令在编译的时候会被删除,也就是说它是在编译之前运行的,在VSIDE下可以展开或者折叠被包围的代码块

UnityShader之创建动态纹理_第1张图片

就像这样

using UnityEngine;
using System.Collections;

public class DynamicP : MonoBehaviour 
{
    //这里的#region是unity的预处理指令,在编译的时候会被删除
    //在vsIDE下可以展开或者折叠被其包围的代码块
    #region Public Variables

    //控制纹理的高和宽
    public int widthHeight = 512;
    public Texture2D generatedTexture;
    #endregion

    #region Private Variables
    //供内部使用的变量,看下边
    private Material currentMaterial;
    private Vector2 centerPosition;
    #endregion


    // Use this for initialization
    void Start () 
    {
        //如果游戏对象没有赋值Material
        if(!currentMaterial)
        {   
            currentMaterial = transform.GetComponent().sharedMaterial;
            //如果经过赋值还没有找到材质,那么就会打印这句警告
            if(!currentMaterial)
            {
                Debug.LogWarning("Cannot find a material on: " + transform.name);
            }
        }

        //如果材质已经被赋值
        if(currentMaterial)
        {

            centerPosition = new Vector2(0.5f, 0.5f);
            //生成抛物线
            generatedTexture = GenerateParabola();

            //给当前的材质设置一个纹理
            currentMaterial.SetTexture("_MainTex", generatedTexture);
        }
        //这句话加上会更容易理解些,没有实际作用
        //Debug.Log(Vector2.Distance(new Vector2(256,256), new Vector2(32,32))/256.0f);
    }

    //生成抛物线纹理的函数 返回2D纹理
    private Texture2D GenerateParabola()
    {
        //创建了新的2D纹理,并指定宽和 高
        Texture2D proceduralTexture = new Texture2D(widthHeight, widthHeight);

        //获得新纹理的中心点坐标
        Vector2 centerPixelPosition = centerPosition * widthHeight;

        //遍历新建纹理的每个像素
        for(int x = 0; x < widthHeight; x++)
        {
            for(int y = 0; y < widthHeight; y++)
            {
                //这个便是当前的每个像素点在图片上的位置
                Vector2 currentPosition = new Vector2(x , y);

                //我们需要的是将像素距离直接映射到0,1的范围内
                //只有(0,1)的值才能被unity当做颜色值来使用
                float pixelDistance = Vector2.Distance(currentPosition, centerPixelPosition)/(widthHeight*0.5f);

                //为了确保值得范围在(0,1)之间,并取其绝对值
                //用1- 取反 得到新的颜色值
                pixelDistance = Mathf.Abs(1-Mathf.Clamp(pixelDistance, 0f,1f));

                //因为要实现的是环绕纹理中心的环形,所以这里需要处理环形的角度,最后乘以颜色值,加深了物体表面的颜色
                //大家可以换个角度试试效果
                  pixelDistance = (Mathf.Sin(pixelDistance * 30.0f) * pixelDistance);
                //pixelDistance = (Mathf.Sin(pixelDistance * 15.0f) * pixelDistance);


                //计算像素方向相对世界方向的角度
                //中心点的像素坐标到 当前的物体相对世界坐标系位置的角度
                //Vector2 pixelDirection = centerPixelPosition - currentPosition;
                //pixelDirection.Normalize();

                //计算像素点相对于x轴的旋转角度
                //float rightDirection = Vector2.Angle(pixelDirection, //Vector3.right)/360;
                //计算像素点相对于x轴的负半轴的旋转角度
                //float leftDirection = Vector2.Angle(pixelDirection, Vector3.left)/360;
                //计算像素点相对于y轴的旋转角度
                //float upDirection = Vector2.Angle(pixelDirection, Vector3.up)/360;

                //新的颜色值

                Color pixelColor = new Color(pixelDistance, pixelDistance, pixelDistance, 1.0f);
                proceduralTexture.SetPixel(x,y,pixelColor);
            }
        }
        //最后把像素应用到纹理
        proceduralTexture.Apply();

        //输出
        return proceduralTexture;
    }
}

效果图
UnityShader之创建动态纹理_第2张图片

这里对形成环形纹理那行代码进行简单的说明
pixelDistance = (Mathf.Sin(pixelDistance * 30.0f) * pixelDistance);
这里,用了正弦函数,是形成环形纹理的关键,新生成的颜色值 pixelDistance,一定要记住它被限制在0,1之间,这就是像素中心距的正弦运算,最后是加深颜色表现,可以把最后的 pixelDistance删掉
下面是将30.0f改成 15.0f的效果图

UnityShader之创建动态纹理_第3张图片

你可能感兴趣的:(unity3d特效)