Uinty3d 镜面反射代码
镜面反射代码
文件名MirrorReflection.cs
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | using UnityEngine;using System.Collections;// This is in fact just the Water script from Pro Standard Assets,// just with refraction stuff removed.[ExecuteInEditMode] // Make mirror live-update even when not in play modepublic classMirrorReflection : MonoBehaviour{     public bool m_DisablePixelLights = true;     public int m_TextureSize = 256;     public float m_ClipPlaneOffset = 0.07f;     public LayerMask m_ReflectLayers = -1;     privateHashtable m_ReflectionCameras = newHashtable(); // Camera -> Camera table     privateRenderTexture m_ReflectionTexture = null;     privateint m_OldReflectionTextureSize = 0;     privatestaticbool 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( m_DisablePixelLights )                 QualitySettings.pixelLightCount = 0;          UpdateCameraModes( cam, reflectionCamera );          // Render reflection          // Reflect camera around reflection plane          float d = -Vector3.Dot (normal, pos) - m_ClipPlaneOffset;          Vector4 reflectionPlane = newVector4 (normal.x, normal.y, normal.z, d);          Matrix4x4 reflection = Matrix4x4.zero;          CalculateReflectionMatrix (ref reflection, 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 = CameraSpacePlane( reflectionCamera, pos, normal, 1.0f );          Matrix4x4 projection = cam.projectionMatrix;          CalculateObliqueMatrix (ref projection, clipPlane);          reflectionCamera.projectionMatrix = projection;          reflectionCamera.cullingMask = ~(1<<4) & m_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 = newVector3(0, euler.y, euler.z);          reflectionCamera.Render();          reflectionCamera.transform.position = oldpos;          GL.SetRevertBackfacing (false);          Material[] materials = renderer.sharedMaterials;          foreach( Material mat inmaterials ) {                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(         newVector3(0.5f,0.5f,0.5f), Quaternion.identity, newVector3(0.5f,0.5f,0.5f) );         Vector3 scale = transform.lossyScale;         Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale( newVector3(1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z) );         mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;         foreach( Material mat inmaterials ) {               mat.SetMatrix( "_ProjMatrix", mtx );         }         // Restore pixel light count         if( m_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 inm_ReflectionCameras )         DestroyImmediate( ((Camera)kvp.Value).gameObject );         m_ReflectionCameras.Clear();    }    privatevoid UpdateCameraModes( Camera src, Camera dest )    {         if( dest == null)                return;         // set camera to clear the same way as current camera         dest.clearFlags = src.clearFlags;         dest.backgroundColor = src.backgroundColor;          if( src.clearFlags == CameraClearFlags.Skybox )         {                Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;                Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;                if( !sky || !sky.material )                {                      mysky.enabled = false;                }                else               {                     mysky.enabled = true;                     mysky.material = sky.material;                }         }         // update other values to match current camera.         // even if we are supplying custom camera&projection matrices,         // some of values are used elsewhere (e.g. skybox uses far plane)         dest.farClipPlane = src.farClipPlane;         dest.nearClipPlane = src.nearClipPlane;         dest.orthographic = src.orthographic;         dest.fieldOfView = src.fieldOfView;         dest.aspect = src.aspect;         dest.orthographicSize = src.orthographicSize;     }     // On-demand create any objects we need     privatevoid CreateMirrorObjects( Camera currentCamera, out Camera reflectionCamera )     {          reflectionCamera = null;          // Reflection render texture          if( !m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureSize )          {                if( m_ReflectionTexture )                     DestroyImmediate( m_ReflectionTexture );                m_ReflectionTexture = newRenderTexture( m_TextureSize, m_TextureSize, 16 );                m_ReflectionTexture.name = "__MirrorReflection"+ GetInstanceID();                m_ReflectionTexture.isPowerOfTwo = true;                m_ReflectionTexture.hideFlags = HideFlags.DontSave;                m_OldReflectionTextureSize = m_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 = newGameObject( "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;          }      }     // Extended sign: returns -1, 0 or 1 based on sign of a     privatestaticfloat sgn(float a)    {          if(a > 0.0f) return1.0f;              if(a < 0.0f) return-1.0f;                   return0.0f;    }    // Given position/normal of the plane, calculates plane in camera space.    privateVector4 CameraSpacePlane (Camera cam, Vector3 pos, Vector3 normal, float sideSign)    {          Vector3 offsetPos = pos + normal * m_ClipPlaneOffset;          Matrix4x4 m = cam.worldToCameraMatrix;          Vector3 cpos = m.MultiplyPoint( offsetPos );          Vector3 cnormal = m.MultiplyVector( normal ).normalized * sideSign;          returnnewVector4( cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal) );    }    // Adjusts the given projection matrix so that near plane is the given clipPlane    // clipPlane is given in camera space. See article in Game Programming Gems 5.    privatestaticvoid CalculateObliqueMatrix (ref Matrix4x4 projection, Vector4 clipPlane)    {          Vector4 q = projection.inverse * newVector4(sgn(clipPlane.x),sgn(clipPlane.y),1.0f,1.0f);          Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlane, q)));          // third row = clip plane - fourth row          projection[2] = c.x - projection[3];          projection[6] = c.y - projection[7];          projection[10] = c.z - projection[11];          projection[14] = c.w - projection[15];    }    // Calculates reflection matrix around the given plane    privatestaticvoid CalculateReflectionMatrix (ref Matrix4x4 reflectionMat, Vector4 plane)    {         reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);         reflectionMat.m01 = ( - 2F*plane[0]*plane[1]);         reflectionMat.m02 = ( - 2F*plane[0]*plane[2]);         reflectionMat.m03 = ( - 2F*plane[3]*plane[0]);         reflectionMat.m10 = ( - 2F*plane[1]*plane[0]);         reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);         reflectionMat.m12 = ( - 2F*plane[1]*plane[2]);         reflectionMat.m13 = ( - 2F*plane[3]*plane[1]);         reflectionMat.m20 = ( - 2F*plane[2]*plane[0]);         reflectionMat.m21 = ( - 2F*plane[2]*plane[1]);         reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);         reflectionMat.m23 = ( - 2F*plane[3]*plane[2]);         reflectionMat.m30 = 0F;         reflectionMat.m31 = 0F;         reflectionMat.m32 = 0F;         reflectionMat.m33 = 1F;    }} | 
文件名MirrorReflection.shader
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | Shader "FX/Mirror Reflection"{       Properties {            _MainTex ("Base (RGB)", 2D) = "white"{}            _ReflectionTex ("Reflection", 2D) = "white"{ TexGen ObjectLinear }      }      // two texture cards: full thing     Subshader {            Pass {                 SetTexture[_MainTex] { combine texture }                 SetTexture[_ReflectionTex] { matrix [_ProjMatrix] combine texture * previous }           }     }     // fallback: just main texture     Subshader {           Pass {                 SetTexture [_MainTex] { combine texture }           }     }} | 
    失败是什么?没有什么,只是更走近成功一步;成功是什么?就是走过了所有通向失败的路,只剩下一条路,那就是成功的路。
 
                     
                    
                 
                    
                 
                
            
         
 
         浙公网安备 33010602011771号
浙公网安备 33010602011771号