UnityShader之创建动态纹理

来源:互联网 发布:it技能 编辑:程序博客网 时间:2024/06/07 19:44

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

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

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

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

这里写图片描述

就像这样

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<Renderer>().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;    }}

效果图
这里写图片描述

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

这里写图片描述

0 0
原创粉丝点击