当前位置:   article > 正文

shader之——湖水(河流倒影)_shader 倒影

shader 倒影

先上图

 

1.水shader

 

  1. Shader "Game_XXX/whater" {
  2. Properties {
  3. _WaterTex ("Normal Map (RGB), Foam (A)", 2D) = "white" {}
  4. _WaterTex2 ("Normal Map (RGB), Foam (B)", 2D) = "white" {}
  5. _Tiling ("Wave Scale", Range(0.00025, 0.1)) = 0.25
  6. _WaveSpeed("Wave Speed", Float) = 0.4
  7. _SpecularRatio ("Specular Ratio", Range(10,500)) = 200
  8. _BottomColor("Bottom Color",Color) = (0,0,0,0)
  9. _TopColor("Top Color",Color) = (0,0,0,0)
  10. _Alpha("Alpha",Range(0,1)) = 1
  11. _ReflectionTex("_ReflectionTex", 2D) = "black" {}
  12. _ReflectionLight("ReflectionLight",Range(0,1)) = 0.3
  13. _LightColorSelf ("LightColorSelf",Color) = (1,1,1,1)
  14. _LightDir ("LightDir",vector) = (0,1,0,0)
  15. }
  16. SubShader {
  17. Tags {
  18. "Queue"="Transparent-200"
  19. "RenderType"="Transparent"
  20. "IgnoreProjector" = "True"
  21. "LightMode" = "ForwardBase"
  22. }
  23. LOD 250
  24. Pass{
  25. Lighting On
  26. ZWrite On
  27. Blend SrcAlpha OneMinusSrcAlpha
  28. CGPROGRAM
  29. #pragma vertex Vert
  30. #pragma fragment Frag
  31. #include "UnityCG.cginc"
  32. float _Tiling;
  33. float _WaveSpeed;
  34. float _SpecularRatio;
  35. sampler2D _WaterTex;
  36. sampler2D _WaterTex2;
  37. sampler2D _ReflectionTex;
  38. float4 _LightColorSelf;
  39. float4 _LightDir;
  40. float4 _BottomColor;
  41. float4 _TopColor;
  42. float _Alpha;
  43. float _ReflectionLight;
  44. struct v2f
  45. {
  46. float4 position : POSITION;
  47. float3 worldPos : TEXCOORD0;
  48. float3 tilingAndOffset:TEXCOORD2;
  49. float4 screen:TEXCOORD3;
  50. float4 VertColor :TEXCOORD4;
  51. };
  52. v2f Vert(appdata_full v)
  53. {
  54. v2f o;
  55. o.worldPos = mul(unity_ObjectToWorld, v.vertex);
  56. o.position = UnityObjectToClipPos(v.vertex);
  57. //uv动画
  58. o.tilingAndOffset.z =frac( _Time.x * _WaveSpeed);
  59. o.tilingAndOffset.xy = o.worldPos.xz*_Tiling;
  60. o.screen = ComputeScreenPos(o.position);
  61. o.VertColor = v.color;
  62. return o;
  63. }
  64. float4 Frag(v2f i):COLOR
  65. {
  66. float3 lightColor=_LightColorSelf.rgb*2;
  67. //世界视向量
  68. float3 worldView = -normalize(i.worldPos - _WorldSpaceCameraPos);
  69. float2 tiling = i.tilingAndOffset.xy;
  70. //法线采样
  71. float4 N1 = tex2D(_WaterTex, tiling.yx +float2(i.tilingAndOffset.z,0));
  72. float4 N2 = tex2D(_WaterTex2, tiling.yx -float2(i.tilingAndOffset.z,0));
  73. //两个法线相加,转世界空间,这里没有unpack,所以法线贴图不需要转normal 法线贴图为0-1 两张加起来为0-2 将其x2-2,转换为-2 --2然后将其normalize,变成-1到1
  74. //在遇到两张法线的情况下 ,一般将法线相加 再normalize
  75. float3 worldNormal = normalize((N1.xyz+N2.xyz)*2-2);
  76. //以垂直的方向代替灯光 跟法线做点积 得到漫反射强度
  77. float LdotN = dot(worldNormal, float3(0,1,0));
  78. fixed2 uv = i.screen.xy/(i.screen.w+0.0001);
  79. uv.y = 1-uv.y;
  80. fixed4 refTex = tex2D (_ReflectionTex,uv + worldNormal.xy*0.02 );
  81. //这个变量一般在Forward渲染路径下使用,存储的是重要的pixel光源方向,没错,的确是使用w来判断这个光源的类型的,一般和_LightColor0配合使用
  82. //float3 LView=_WorldSpaceLightPos0.xyz;
  83. float3 LView = _LightDir.xyz;
  84. //if(_WorldSpaceLightPos0.w == 0.0){
  85. // L = normalize(_WorldSpaceLightPos0.xyz);
  86. // }
  87. // else{
  88. // L = normalize(_WorldSpaceLightPos0.xyz - i.worldPos);
  89. // }
  90. //根据世界法线 ,世界视向量+光向量 得出高光 系数
  91. float dotSpecular = dot(worldNormal, normalize( worldView+LView));
  92. //控制高光的范围
  93. float3 specularReflection = pow(saturate(dotSpecular), _SpecularRatio);
  94. float4 col;
  95. float fresnel = 0.5*LdotN+0.5;
  96. //根据法线的强度 来确定两种颜色之间的混合 ????
  97. col.rgb = lerp(_BottomColor.xyz, _TopColor.xyz, fresnel);
  98. col.rgb = saturate (LdotN) *col.rgb;
  99. //加上高光
  100. col.rgb += specularReflection;
  101. col.rgb = lerp (col.rgb,refTex.rgb*_ReflectionLight,0.7);
  102. //col.rgb +=refTex.rgb*_ReflectionLight;
  103. //加上灯光颜色
  104. col.rgb*=lightColor;
  105. col.rgb *= i.VertColor.rgb;
  106. //控制透明度
  107. col.a =i.VertColor.a * _Alpha;
  108. return col;
  109. }
  110. ENDCG
  111. }
  112. }
  113. FallBack "Diffuse"
  114. }


2.c# 反射

 

 

 

 

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. [ExecuteInEditMode]
  5. public class ReflectionSelf : MonoBehaviour {
  6. private Transform refObject;
  7. private Camera m_camera;
  8. public LayerMask reflectionMask;
  9. private RenderTexture m_texture;
  10. void Start () {
  11. refObject = this.GetComponent<Transform>();
  12. GameObject refCramera = new GameObject("refCramera");
  13. m_camera = refCramera.AddComponent<Camera>();
  14. m_texture = new RenderTexture(Screen.width,Screen.height,24);
  15. refCameraSet();
  16. }
  17. /// <summary>
  18. /// 相机位置及方向
  19. /// </summary>
  20. void cameraTrasform()
  21. {
  22. //Position x z 与mainCamera相同 y 到平面的距离与 mainCamera到平面的距离相等
  23. Vector3 p_ref;
  24. Vector3 p_main = Camera.main.transform.position;
  25. Vector3 p_plan = this.transform.position;
  26. float y = p_main.y - p_plan.y;
  27. p_ref.x = p_main.x;
  28. p_ref.y = p_plan.y - y;
  29. p_ref.z = p_main.z;
  30. m_camera.transform.position = p_ref;
  31. //Rotation
  32. Vector3 R_ref;
  33. Vector3 R_main = Camera.main.transform.localEulerAngles;
  34. R_ref.x = -R_main.x;
  35. R_ref.y = R_main.y;
  36. R_ref.z = R_main.z;
  37. m_camera.transform.localEulerAngles = R_ref;
  38. }
  39. /// <summary>
  40. /// 反射相机的设置
  41. /// </summary>
  42. void refCameraSet()
  43. {
  44. m_camera.backgroundColor = Color.black;
  45. m_camera.clearFlags = CameraClearFlags.Skybox;
  46. m_camera.cullingMask = reflectionMask; //图层
  47. m_camera.targetTexture = m_texture;
  48. this.GetComponent<Renderer>().sharedMaterial.SetTexture("_ReflectionTex", m_camera.targetTexture);
  49. }
  50. void Update () {
  51. //相机位置要放在这里,因为要随着主相机一直运动
  52. cameraTrasform();
  53. }
  54. }


3.曾经在官方的demo里看到反射相机的写法 比较复杂 在此也贴出来 用这个脚本的话 需要把水的shader里面屏幕UV的y方向变为正方向

 

 

 

 

  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. //[ExecuteInEditMode]
  4. public class ReflectionFx : MonoBehaviour
  5. {
  6. public Transform[] reflectiveObjects;
  7. public LayerMask reflectionMask;
  8. public Material[] reflectiveMaterials;
  9. private Transform reflectiveSurfaceHeight;
  10. public Shader replacementShader;
  11. private bool highQuality = false;
  12. public Color clearColor = Color.black;
  13. public System.String reflectionSampler = "_ReflectionTex";
  14. public float clipPlaneOffset = 0.07F;
  15. private Vector3 oldpos = Vector3.zero;
  16. //反射相机
  17. private Camera reflectionCamera;
  18. private Dictionary<Camera, bool> helperCameras = null;
  19. private Texture[] initialReflectionTextures;
  20. public void Start()
  21. {
  22. initialReflectionTextures = new Texture2D[reflectiveMaterials.Length];
  23. for (int i = 0; i < reflectiveMaterials.Length; i++)
  24. {
  25. initialReflectionTextures[i] = reflectiveMaterials[i].GetTexture(reflectionSampler);
  26. }
  27. this.enabled = true;
  28. }
  29. public void OnDisable()
  30. {
  31. if (initialReflectionTextures == null)
  32. return;
  33. // restore initial reflection textures
  34. for (int i = 0; i < reflectiveMaterials.Length; i++)
  35. {
  36. reflectiveMaterials[i].SetTexture(reflectionSampler, initialReflectionTextures[i]);
  37. }
  38. }
  39. //创建新相机
  40. private Camera CreateReflectionCameraFor(Camera cam)
  41. {
  42. //将string类初始化,挂脚本的物体名 + “Reflection” + 输入的cam名字
  43. System.String reflName = gameObject.name + "Reflection" + cam.name;
  44. //Debug.Log("AngryBots: created internal reflection camera " + reflName);
  45. //找到这个名字的物体,并将go 实例化
  46. GameObject go = GameObject.Find(reflName);
  47. if (!go) //如果这个物体不存在
  48. go = new GameObject(reflName, typeof(Camera)); //再重新创建一个新的物体,给他赋上名字和类型
  49. if (!go.GetComponent(typeof(Camera))) //这个物体没有Camera组件
  50. go.AddComponent(typeof(Camera));//给它加上Camera组件
  51. Camera reflectCamera = go.GetComponent<Camera>(); //reflectCamera实例化为这个物体(go)的相机组件
  52. reflectCamera.backgroundColor = clearColor; //相机的背景颜色 把背景色设置为clearColor 就不会遮盖住背后的视图
  53. reflectCamera.clearFlags = CameraClearFlags.Skybox;//清楚标记,SolidColor:屏幕上的任何空的部分将显示当前相机的背景颜色
  54. SetStandardCameraParameter(reflectCamera, reflectionMask);//设置渲染图层
  55. if (!reflectCamera.targetTexture) //如果反射相机没有targetTexture
  56. reflectCamera.targetTexture = CreateTextureFor(cam); //用这个方法创建targetTexture赋给相机的targetTexture
  57. return reflectCamera;
  58. }
  59. public void HighQuality()
  60. {
  61. highQuality = true;
  62. }
  63. //设置反射相机的渲染图层
  64. private void SetStandardCameraParameter(Camera cam, LayerMask mask)
  65. {
  66. cam.backgroundColor = Color.black; //背景色为黑色
  67. cam.enabled = true; //cam为false状态?
  68. cam.cullingMask = reflectionMask; //设置渲染图层
  69. }
  70. //给相机赋上targetTexture
  71. private RenderTexture CreateTextureFor(Camera cam)
  72. {
  73. RenderTextureFormat rtFormat = RenderTextureFormat.RGB565;
  74. if (!SystemInfo.SupportsRenderTextureFormat(rtFormat))
  75. rtFormat = RenderTextureFormat.Default;
  76. float rtSizeMul = highQuality ? 0.75f : 0.5f;
  77. RenderTexture rt = new RenderTexture(Mathf.FloorToInt(cam.pixelWidth * rtSizeMul), Mathf.FloorToInt(cam.pixelHeight * rtSizeMul), 24, rtFormat);
  78. rt.hideFlags = HideFlags.DontSave;
  79. return rt;
  80. }
  81. public void RenderHelpCameras(Camera currentCam)
  82. {
  83. if (null == helperCameras)
  84. helperCameras = new Dictionary<Camera, bool>();
  85. if (!helperCameras.ContainsKey(currentCam))
  86. {
  87. helperCameras.Add(currentCam, false);
  88. }
  89. if (helperCameras[currentCam])
  90. {
  91. return;
  92. }
  93. if (!reflectionCamera)
  94. {
  95. reflectionCamera = CreateReflectionCameraFor(currentCam);
  96. foreach (Material m in reflectiveMaterials)
  97. {
  98. m.SetTexture(reflectionSampler, reflectionCamera.targetTexture);
  99. }
  100. }
  101. RenderReflectionFor(currentCam, reflectionCamera);
  102. helperCameras[currentCam] = true;
  103. }
  104. public void LateUpdate()
  105. {
  106. // find the closest reflective surface and use that as our
  107. // reference for reflection height etc.
  108. //找到最接近的反射面并将其作为我们的
  109. //参考高度等。
  110. Transform closest = null;
  111. float closestDist = Mathf.Infinity;
  112. Vector3 pos = Camera.main.transform.position;
  113. foreach (Transform t in reflectiveObjects)
  114. {
  115. if (t.GetComponent<Renderer>().isVisible)
  116. {
  117. float dist = (pos - t.position).sqrMagnitude;
  118. if (dist < closestDist)
  119. {
  120. closestDist = dist;
  121. closest = t;
  122. }
  123. }
  124. }
  125. if (!closest)
  126. return;
  127. ObjectBeingRendered(closest, Camera.main);
  128. if (null != helperCameras)
  129. helperCameras.Clear();
  130. }
  131. private void ObjectBeingRendered(Transform tr, Camera currentCam)
  132. {
  133. if (null == tr)
  134. return;
  135. reflectiveSurfaceHeight = tr;
  136. RenderHelpCameras(currentCam);
  137. }
  138. private void RenderReflectionFor(Camera cam, Camera reflectCamera)
  139. {
  140. if (!reflectCamera)
  141. return;
  142. SaneCameraSettings(reflectCamera);
  143. reflectCamera.backgroundColor = clearColor;
  144. //GL.SetRevertBackfacing(true);
  145. GL.invertCulling = true;
  146. Transform reflectiveSurface = reflectiveSurfaceHeight;
  147. Vector3 eulerA = cam.transform.eulerAngles;
  148. reflectCamera.transform.eulerAngles = new Vector3(-eulerA.x, eulerA.y, eulerA.z);
  149. reflectCamera.transform.position = cam.transform.position;
  150. Vector3 pos = reflectiveSurface.transform.position;
  151. pos.y = reflectiveSurface.position.y;
  152. Vector3 normal = reflectiveSurface.transform.up;
  153. float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
  154. Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
  155. Matrix4x4 reflection = Matrix4x4.zero;
  156. reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
  157. oldpos = cam.transform.position;
  158. Vector3 newpos = reflection.MultiplyPoint(oldpos);
  159. reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
  160. Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
  161. Matrix4x4 projection = cam.projectionMatrix;
  162. projection = CalculateObliqueMatrix(projection, clipPlane);
  163. reflectCamera.projectionMatrix = projection;
  164. reflectCamera.transform.position = newpos;
  165. Vector3 euler = cam.transform.eulerAngles;
  166. reflectCamera.transform.eulerAngles = new Vector3(-euler.x, euler.y, euler.z);
  167. reflectCamera.RenderWithShader(replacementShader, "Reflection");
  168. //GL.SetRevertBackfacing(false);
  169. GL.invertCulling = false;
  170. }
  171. private void SaneCameraSettings(Camera helperCam)
  172. {
  173. helperCam.depthTextureMode = DepthTextureMode.None;
  174. helperCam.backgroundColor = Color.black;
  175. helperCam.clearFlags = CameraClearFlags.Skybox;
  176. helperCam.renderingPath = RenderingPath.Forward;
  177. }
  178. static Matrix4x4 CalculateObliqueMatrix(Matrix4x4 projection, Vector4 clipPlane)
  179. {
  180. Vector4 q = projection.inverse * new Vector4(
  181. sgn(clipPlane.x),
  182. sgn(clipPlane.y),
  183. 1.0F,
  184. 1.0F
  185. );
  186. Vector4 c = clipPlane * (2.0F / (Vector4.Dot(clipPlane, q)));
  187. // third row = clip plane - fourth row
  188. projection[2] = c.x - projection[3];
  189. projection[6] = c.y - projection[7];
  190. projection[10] = c.z - projection[11];
  191. projection[14] = c.w - projection[15];
  192. return projection;
  193. }
  194. // Helper function for getting the reflection matrix that will be multiplied with camera matrix
  195. //用摄像机矩阵来得到反射矩阵的辅助函数
  196. static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
  197. {
  198. reflectionMat.m00 = (1.0F - 2.0F * plane[0] * plane[0]);
  199. reflectionMat.m01 = (-2.0F * plane[0] * plane[1]);
  200. reflectionMat.m02 = (-2.0F * plane[0] * plane[2]);
  201. reflectionMat.m03 = (-2.0F * plane[3] * plane[0]);
  202. reflectionMat.m10 = (-2.0F * plane[1] * plane[0]);
  203. reflectionMat.m11 = (1.0F - 2.0F * plane[1] * plane[1]);
  204. reflectionMat.m12 = (-2.0F * plane[1] * plane[2]);
  205. reflectionMat.m13 = (-2.0F * plane[3] * plane[1]);
  206. reflectionMat.m20 = (-2.0F * plane[2] * plane[0]);
  207. reflectionMat.m21 = (-2.0F * plane[2] * plane[1]);
  208. reflectionMat.m22 = (1.0F - 2.0F * plane[2] * plane[2]);
  209. reflectionMat.m23 = (-2.0F * plane[3] * plane[2]);
  210. reflectionMat.m30 = 0.0F;
  211. reflectionMat.m31 = 0.0F;
  212. reflectionMat.m32 = 0.0F;
  213. reflectionMat.m33 = 1.0F;
  214. return reflectionMat;
  215. }
  216. // Extended sign: returns -1, 0 or 1 based on sign of a
  217. //扩展符号:返回-1、0或1,基于a的符号
  218. static float sgn(float a)
  219. {
  220. if (a > 0.0F) return 1.0F;
  221. if (a < 0.0F) return -1.0F;
  222. return 0.0F;
  223. }
  224. // Given position/normal of the plane, calculates plane in camera space.
  225. //给定平面的正/正态,在相机空间计算平面
  226. private Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
  227. {
  228. Vector3 offsetPos = pos + normal * clipPlaneOffset;
  229. Matrix4x4 m = cam.worldToCameraMatrix;
  230. Vector3 cpos = m.MultiplyPoint(offsetPos);
  231. Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
  232. return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
  233. }
  234. }

亲,如果您觉得本文不错,愿意给我一些动力的话,请用手机扫描二维码即可向我打赏

                                         打赏

 

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/108466
推荐阅读
相关标签
  

闽ICP备14008679号