Unity3d 镜面折射 vertex and frag Shader源码

来源:互联网 发布:mac搜索不到蓝牙音箱 编辑:程序博客网 时间:2024/06/05 10:20

Unity3d 镜面折射 

网上能找到的基本上是固定管道或表面渲染的shader,

特此翻译为顶点、片段渲染的Shader,

本源码只涉及shader与cs部分,

请自行下载NGUI 

unity3d 版本:v4.3.1

RefractionMirror.cs

using UnityEngine;using System.Collections;using System;/// <summary>/// 镜面折射效果/// </summary>[AddComponentMenu("GameCore/Effect/Refraction/Mirror")][ExecuteInEditMode]public class RefractionMirror : MonoBehaviour{    public bool DisablePixelLights = true;    public int TextureSize = 512;    public float ClipPlaneOffset = 0;    public LayerMask ReflectLayers = -1;    private Hashtable _RefractionCameras = new Hashtable(); // Camera -> Camera table    private RenderTexture _RefractionTexture = null;    private int _OldRefractionTextureSize = 0;    private static bool _InsideRendering = false;    // This is called when it's known that the object will be rendered by some    // camera. We render Refractions and do other updates here.    // Because the script executes in edit mode, Refractions for the scene view    // camera will just work!    void OnWillRenderObject()    {        if (!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)            return;        Camera cam = Camera.current;        if (!cam)            return;        // Safeguard from recursive Refractions.                if (_InsideRendering)            return;        _InsideRendering = true;        Camera RefractionCamera;        CreateMirrorObjects(cam, out RefractionCamera);        // find out the Refraction plane: position and normal in world space        Vector3 pos = transform.position;        Vector3 normal = transform.up;        // Optionally disable pixel lights for Refraction        int oldPixelLightCount = QualitySettings.pixelLightCount;        if (DisablePixelLights)            QualitySettings.pixelLightCount = 0;        CoreTool.CloneCameraModes(cam, RefractionCamera);        RefractionCamera.cullingMask = ~(1 << 4) & ReflectLayers.value; // never render water layer        RefractionCamera.targetTexture = _RefractionTexture;        RefractionCamera.transform.position = cam.transform.position;        RefractionCamera.transform.eulerAngles = cam.transform.eulerAngles;        RefractionCamera.Render();                Material[] materials = renderer.sharedMaterials;        foreach (Material mat in materials)        {            if (mat.HasProperty("_RefractionTex"))                mat.SetTexture("_RefractionTex", _RefractionTexture);        }        // Set matrix on the shader that transforms UVs from object space into screen        // space. We want to just project Refraction texture on screen.        Matrix4x4 scaleOffset = Matrix4x4.TRS(            new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f));        Vector3 scale = transform.lossyScale;        Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z));        mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;        foreach (Material mat in materials)        {            mat.SetMatrix("_ProjMatrix", mtx);        }        // Restore pixel light count        if (DisablePixelLights)            QualitySettings.pixelLightCount = oldPixelLightCount;        _InsideRendering = false;    }    // Cleanup all the objects we possibly have created    void OnDisable()    {        if (_RefractionTexture)        {            DestroyImmediate(_RefractionTexture);            _RefractionTexture = null;        }        foreach (DictionaryEntry kvp in _RefractionCameras)            DestroyImmediate(((Camera)kvp.Value).gameObject);        _RefractionCameras.Clear();    }    // On-demand create any objects we need    private void CreateMirrorObjects(Camera currentCamera, out Camera RefractionCamera)    {        RefractionCamera = null;        // Refraction render texture        if (!_RefractionTexture || _OldRefractionTextureSize != TextureSize)        {            if (_RefractionTexture)                DestroyImmediate(_RefractionTexture);            _RefractionTexture = new RenderTexture(TextureSize, TextureSize, 0);            _RefractionTexture.name = "__MirrorRefraction" + GetInstanceID();            _RefractionTexture.isPowerOfTwo = true;            _RefractionTexture.hideFlags = HideFlags.DontSave;            _RefractionTexture.antiAliasing = 4;            _RefractionTexture.anisoLevel = 0;            _OldRefractionTextureSize = TextureSize;        }        // Camera for Refraction        RefractionCamera = _RefractionCameras[currentCamera] as Camera;        if (!RefractionCamera) // catch both not-in-dictionary and in-dictionary-but-deleted-GO        {            GameObject go = new GameObject("Mirror Refl Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));            RefractionCamera = go.camera;            RefractionCamera.enabled = false;            RefractionCamera.transform.position = transform.position;            RefractionCamera.transform.rotation = transform.rotation;            RefractionCamera.gameObject.AddComponent("FlareLayer");            go.hideFlags = HideFlags.HideAndDontSave;            _RefractionCameras[currentCamera] = RefractionCamera;        }    }}

shader

Shader "GameCore/Mobile/Refraction/Mirror" {    Properties {        _RefractionTex ("Refraction", 2D) = "white" {TexGen ObjectLinear }_RefractionColor("Color",Color) = (1,1,1,1)}SubShader {        Tags {            "RenderType"="Opaque"}LOD 100Pass {            CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"uniform float4x4 _ProjMatrix;            uniform sampler2D _RefractionTex;            float4 _RefractionColor;            struct outvertex {                float4 pos : SV_POSITION;                float3 uv : TEXCOORD0;                float4 posProj;            };            outvertex vert(appdata_tan v) {                outvertex o;                o.pos = mul (UNITY_MATRIX_MVP,v.vertex);                o.posProj = mul(_ProjMatrix, v.vertex);            return o;            }float4 frag(outvertex i) : COLOR {                half4 reflcol = tex2D(_RefractionTex,float2(i.posProj) / i.posProj.w);                return reflcol*_RefractionColor;            }ENDCG}}}


Shader "GameCore/Refraction/Mirror" {    Properties {        _RefractionTex ("Refraction ", 2D) = "white" {TexGen ObjectLinear }_RefractionColor("Color",Color) = (1,1,1,1)}SubShader {        Tags {            "RenderType"="Opaque"}LOD 100Pass {            CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"uniform float4x4 _ProjMatrix;            uniform sampler2D _RefractionTex;            float4 _RefractionColor;            struct outvertex {                float4 pos : SV_POSITION;                float3 uv : TEXCOORD0;            };            outvertex vert(appdata_tan v) {                outvertex o;                o.pos = mul (UNITY_MATRIX_MVP,v.vertex);                                float3 viewDir = ObjSpaceViewDir(v.vertex);o.uv = mul(_ProjMatrix,float4(viewDir,0));return o;            }float4 frag(outvertex i) : COLOR {                half4 reflcol = tex2Dproj(_RefractionTex,i.uv);                return reflcol*_RefractionColor;            }ENDCG}}}



0 0