Unity投影器细节整理

抽了个空整理下投影器

 

一般投影器需要两张贴图,一张Cookie,一张FallOff。

 

Unity提供Light和Multiple两种自带shader,和粒子类似。

Cookie需要非alpha贴图,FallOff用带Alpha的贴图

 

 

当不使用FallOff贴图时会有侧背面穿透的问题,不管是正交还是透视投影器(Cookie边缘干净时也会)

 

 

实际上使用FallOff贴图也不能解决,但可以避免大部分情况

 

 

FallOff贴图,从左往右对应+Z至-Z范围

 

 

另外写了一个快速生成FallOff渐变贴图的工具脚本

点击创建后,会自动在Assets目录下生成一张名为Gradient的临时贴图

丢Editor目录下即可使用

using UnityEditor;
using UnityEngine;
using System.IO;
using System.Linq;
using System.Collections;

public class GradientCreator : EditorWindow
{
    public enum OrderModeEnum { H, V };

    Color mBeginColor = new Color(1, 1, 1, 1);
    Color mEndColor = new Color(0, 0, 0, 0);
    float mOffset = 1f;
    int mExpectWidth = 256;
    int mExpectHeight = 256;
    bool mIsHardEdge = true;
    bool mIsInvert = false;
    OrderModeEnum mOrderMode;


    [MenuItem("Hont Tools/Gradient Creator")]
    public static void Setup()
    {
        GetWindow<GradientCreator>();
    }

    void OnGUI()
    {
        mBeginColor = EditorGUILayout.ColorField("Begin Color", mBeginColor);
        mEndColor = EditorGUILayout.ColorField("End Color", mEndColor);
        mOffset = EditorGUILayout.Slider("Offset", mOffset, -1, 1);
        mIsInvert = EditorGUILayout.Toggle("Invert", mIsInvert);
        mExpectWidth = EditorGUILayout.IntField("Expect Width", mExpectWidth);
        mExpectHeight = EditorGUILayout.IntField("Expect Height", mExpectHeight);
        mIsHardEdge = EditorGUILayout.Toggle("Hard Edge", mIsHardEdge);

        mOrderMode = (OrderModeEnum)EditorGUILayout.EnumPopup("Order Mode", mOrderMode);

        if (GUILayout.Button("Create!"))
        {
            var mainTexture = new Texture2D(mExpectWidth, mExpectHeight);

            if (mOrderMode == OrderModeEnum.V)
            {
                for (int x = 0; x < mainTexture.width; x++)
                {
                    for (int y = 0; y < mainTexture.height; y++)
                    {
                        var g = GetG(y, mainTexture.height);
                        var currentColor = Color.Lerp(mBeginColor, mEndColor, g);
                        mainTexture.SetPixel(x, y, currentColor);
                    }
                }
            }
            else
            {
                for (int y = 0; y < mainTexture.height; y++)
                {
                    for (int x = 0; x < mainTexture.width; x++)
                    {
                        var g = GetG(x, mainTexture.width);
                        var currentColor = Color.Lerp(mBeginColor, mEndColor, g);
                        mainTexture.SetPixel(x, y, currentColor);
                    }
                }
            }

            mainTexture.Apply();

            var outputFile = System.IO.Directory.GetCurrentDirectory() + "/Assets/Gradient.png";

            if (File.Exists(outputFile))
                File.Delete(outputFile);

            var bytes = mainTexture.EncodeToPNG();
            File.WriteAllBytes(outputFile, bytes);
            AssetDatabase.Refresh();
        }
    }

    float GetG(float current, float max)
    {
        var g = Mathf.Clamp01((current / max) + mOffset);
        g = mIsHardEdge ? g < 1 ? 0f : 1f : g;
        g = mIsInvert ? 1 - g : g;
        return g;
    }
}
Gradient Creator

 

 

关于投影器的实现,我觉得如下:

1.Unity先把投影器影响到的物体剔除出来,然后再对他们进行再次绘制,并且这个绘制是在绘制透明物体的管线阶段下进行的。

2.通过'投影纹理映射'的方法,似乎是tex2Dproj。最终得到映射的UV坐标。进行绘制

 

需要注意,如果影响到的物体越多,dc也就越高,因为都要多绘制一次

posted @ 2017-03-18 15:10  HONT  阅读(1560)  评论(0编辑  收藏  举报