• Unity3d 镜面折射 vertex and frag Shader源代码


    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 100
    		Pass {
                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 100
    		Pass {
                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
    		}
    	}
    }



  • 相关阅读:
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业01
    学期总结
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I博客作业04
    C语言I博客作业03
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10738711.html
  • Copyright © 2020-2023  润新知