zoukankan      html  css  js  c++  java
  • Unity3d 镜面反射 vertex and frag Shader源代码

    Unity3d 镜面反射 

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

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

    本源代码仅仅涉及shader与cs部分。

    Editor部分使用NGUI绘制的,

    请自行下载NGUI 

    unity3d 版本号:v4.3.1

    ReflectionMirror.cs

    using UnityEngine;
    using System.Collections;
    using System;
    
    /// <summary>
    /// 反射效果
    /// </summary>
    [AddComponentMenu("GameCore/SpecialEffect/Reflection Mirror")]
    [ExecuteInEditMode]
    public class ReflectionMirror : MonoBehaviour
    {
        public bool DisablePixelLights = true;
        public int TextureSize = 512;
        public float ClipPlaneOffset = 0;
        public LayerMask ReflectLayers = -1;
    
        private Hashtable m_ReflectionCameras = new Hashtable(); // Camera -> Camera table
        private RenderTexture m_ReflectionTexture = null;
        private int m_OldReflectionTextureSize = 0;
    
        private static bool s_InsideRendering = false;
    
        // This is called when it's known that the object will be rendered by some
        // camera. We render reflections and do other updates here.
        // Because the script executes in edit mode, reflections for the scene view
        // camera will just work!
        public void OnWillRenderObject()
        {
            if (!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)
                return;
    
            Camera cam = Camera.current;
            if (!cam)
                return;
    
            // Safeguard from recursive reflections.        
            if (s_InsideRendering)
                return;
            s_InsideRendering = true;
    
            Camera reflectionCamera;
            CreateMirrorObjects(cam, out reflectionCamera);
    
            // find out the reflection plane: position and normal in world space
            Vector3 pos = transform.position;
            Vector3 normal = transform.up;
            // Optionally disable pixel lights for reflection
            int oldPixelLightCount = QualitySettings.pixelLightCount;
            if (DisablePixelLights)
                QualitySettings.pixelLightCount = 0;
    
            CoreTool.CloneCameraModes(cam, reflectionCamera);
    
            // Render reflection
            // Reflect camera around reflection plane
            float d = -Vector3.Dot(normal, pos) - ClipPlaneOffset;
            Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
    
    
            Matrix4x4 reflection = CoreTool.CalculateReflectionMatrix(Matrix4x4.zero, reflectionPlane);
    
            Vector3 oldpos = cam.transform.position;
            Vector3 newpos = reflection.MultiplyPoint(oldpos);
            reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
    
    
    
            // Setup oblique projection matrix so that near plane is our reflection
            // plane. This way we clip everything below/above it for free.
            Vector4 clipPlane = CoreTool.CameraSpacePlane(reflectionCamera, pos, normal, 1.0f, ClipPlaneOffset);
    
            Matrix4x4 projection = cam.projectionMatrix;
    
            projection = CoreTool.CalculateObliqueMatrix(projection, clipPlane);
    
            reflectionCamera.projectionMatrix = projection;
    
            reflectionCamera.cullingMask = ~(1 << 4) & ReflectLayers.value; // never render water layer
            reflectionCamera.targetTexture = m_ReflectionTexture;
    
            GL.SetRevertBackfacing(true);
            reflectionCamera.transform.position = newpos;
            Vector3 euler = cam.transform.eulerAngles;
            reflectionCamera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
            reflectionCamera.Render();
            reflectionCamera.transform.position = oldpos;
            GL.SetRevertBackfacing(false);
            Material[] materials = renderer.sharedMaterials;
            foreach (Material mat in materials)
            {
                if (mat.HasProperty("_ReflectionTex"))
                    mat.SetTexture("_ReflectionTex", m_ReflectionTexture);
            }
    
            // Set matrix on the shader that transforms UVs from object space into screen
            // space. We want to just project reflection 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;
            s_InsideRendering = false;
        }
    
    
        // Cleanup all the objects we possibly have created
        void OnDisable()
        {
            if (m_ReflectionTexture)
            {
                DestroyImmediate(m_ReflectionTexture);
                m_ReflectionTexture = null;
            }
            foreach (DictionaryEntry kvp in m_ReflectionCameras)
                DestroyImmediate(((Camera)kvp.Value).gameObject);
            m_ReflectionCameras.Clear();
        }
    
        // On-demand create any objects we need
        private void CreateMirrorObjects(Camera currentCamera, out Camera reflectionCamera)
        {
            reflectionCamera = null;
            
            // Reflection render texture
            if (!m_ReflectionTexture || m_OldReflectionTextureSize != TextureSize)
            {
                if (m_ReflectionTexture)
                    DestroyImmediate(m_ReflectionTexture);
                m_ReflectionTexture = new RenderTexture(TextureSize, TextureSize,0);
                m_ReflectionTexture.name = "__MirrorReflection" + GetInstanceID();
                m_ReflectionTexture.isPowerOfTwo = true;
                m_ReflectionTexture.hideFlags = HideFlags.DontSave;
                m_ReflectionTexture.antiAliasing = 4;
                m_ReflectionTexture.anisoLevel = 0;
                m_OldReflectionTextureSize = TextureSize;
            }
    
            // Camera for reflection
            reflectionCamera = m_ReflectionCameras[currentCamera] as Camera;
            if (!reflectionCamera) // 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));
                reflectionCamera = go.camera;
                reflectionCamera.enabled = false;
                reflectionCamera.transform.position = transform.position;
                reflectionCamera.transform.rotation = transform.rotation;
                reflectionCamera.gameObject.AddComponent("FlareLayer");
                go.hideFlags = HideFlags.HideAndDontSave;
                m_ReflectionCameras[currentCamera] = reflectionCamera;
            }
        }
    }
    

    ReflectionMirrorEditor.cs

    using System.Collections;
    using System;
    using UnityEditor;
    using UnityEngine;
    /// <summary>
    /// 反射效果
    /// </summary>
    [CustomEditor(typeof(ReflectionMirror))]
    public class ReflectionMirrorEditor : Editor
    {
        string[] _renderTextureOptions = new string[8] { "16", "32", "64", "128", "256", "512", "1024", "2048" };
        int _renderTextureWidthDefaultIndex = 5;
        int _renderTextureWidthIndex = 5;
        SerializedProperty _sp;
        public override void OnInspectorGUI()
        {
            EditorGUILayout.HelpBox("This the reflection effect,it has mirror or sphere reflection!",MessageType.Info);
            if (NGUIEditorTools.DrawHeader("Reflection Settings"))
            {
                NGUIEditorTools.BeginContents();
                {                
                    NGUIEditorTools.DrawProperty("Disable PixelLights", this.serializedObject, "DisablePixelLights");
                    NGUIEditorTools.DrawProperty("Reflect Layers", this.serializedObject, "ReflectLayers");                
                    NGUIEditorTools.DrawProperty("ClipPlane Offset", this.serializedObject, "ClipPlaneOffset");
                }
                NGUIEditorTools.EndContents();
            }
            if (NGUIEditorTools.DrawHeader("Render Texture Settings"))
            {
                NGUIEditorTools.BeginContents();
                {
                    _sp = this.serializedObject.FindProperty("TextureSize");
                    _renderTextureWidthIndex = GetTextureOptionsIndex(_sp.intValue.ToString());
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("TexSize:", GUILayout.Width(100));
                    _renderTextureWidthIndex = EditorGUILayout.Popup(_renderTextureWidthIndex, _renderTextureOptions);
                    EditorGUILayout.EndHorizontal();
    
                    if (GUILayout.Button("Make Default Value"))
                    {
                        _renderTextureWidthIndex = _renderTextureWidthDefaultIndex;
                    }
                    _sp.intValue = int.Parse(_renderTextureOptions[_renderTextureWidthIndex]);
                }
                NGUIEditorTools.EndContents();
            }
    
            this.serializedObject.ApplyModifiedProperties();
        }
    
        int GetTextureOptionsIndex(string value)
        {
            int index = 0;
            for (int i = 0; i < _renderTextureOptions.Length; i++)
            {
                if (_renderTextureOptions[i].Equals(value, StringComparison.OrdinalIgnoreCase))
                {
                    index = i;
                }
            }
            return index;
        }
    }
    

    Shader

    Shader "GameCore/SpecialEffect/Reflection Mirror"
    {
        Properties {
            _ReflectionTex ("Reflection", 2D) = "white" {TexGen ObjectLinear }
    		_ReflectionColor("Color",Color) = (1,1,1,1)
    	}
    	//PC
    	SubShader {
            Tags {
                "RenderType"="Opaque"}
    		LOD 100
    		Pass {
                CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#include "UnityCG.cginc"
    
    			uniform float4x4 _ProjMatrix;
                uniform sampler2D _ReflectionTex;
                float4 _ReflectionColor;
                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(_ReflectionTex,i.uv);				
                    return reflcol*_ReflectionColor;
                }
    			ENDCG
    		}
    	}
    	//Mobile
    	SubShader {
            Tags {
                "RenderType"="Opaque"}
    		LOD 100
    		Pass {
                CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			#include "UnityCG.cginc"
    
    			uniform float4x4 _ProjMatrix;
                uniform sampler2D _ReflectionTex;
                float4 _ReflectionColor;
                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(_ReflectionTex,float2(i.posProj) / i.posProj.w);
                    return reflcol*_ReflectionColor;
                }
    			ENDCG
    		}
    	}
    }

    来源链接: http://pan.baidu.com/s/1gdyzyNL

  • 相关阅读:
    JAVA字符串格式化-String.format()的使用
    分布式文件系统MFS(moosefs)实现存储共享(第二版)
    iOS 动画学习
    复制对象(一)copy和mutableCopy方法
    iOS-获取当前网页的 url 和 title 和 html
    排序算法 c实现
    常用正则表达式
    iOS-获取的NSDate date时间与实际相差8个小时解决方案
    网络爬虫基本原理(二)
    网络爬虫基本原理(一)
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4869383.html
Copyright © 2011-2022 走看看