赞
踩
先上图
1.水shader
- Shader "Game_XXX/whater" {
- Properties {
- _WaterTex ("Normal Map (RGB), Foam (A)", 2D) = "white" {}
- _WaterTex2 ("Normal Map (RGB), Foam (B)", 2D) = "white" {}
-
- _Tiling ("Wave Scale", Range(0.00025, 0.1)) = 0.25
- _WaveSpeed("Wave Speed", Float) = 0.4
-
-
- _SpecularRatio ("Specular Ratio", Range(10,500)) = 200
-
- _BottomColor("Bottom Color",Color) = (0,0,0,0)
- _TopColor("Top Color",Color) = (0,0,0,0)
- _Alpha("Alpha",Range(0,1)) = 1
-
- _ReflectionTex("_ReflectionTex", 2D) = "black" {}
- _ReflectionLight("ReflectionLight",Range(0,1)) = 0.3
-
- _LightColorSelf ("LightColorSelf",Color) = (1,1,1,1)
- _LightDir ("LightDir",vector) = (0,1,0,0)
-
-
-
- }
-
- SubShader {
- Tags {
- "Queue"="Transparent-200"
- "RenderType"="Transparent"
- "IgnoreProjector" = "True"
- "LightMode" = "ForwardBase"
- }
- LOD 250
- Pass{
- Lighting On
- ZWrite On
- Blend SrcAlpha OneMinusSrcAlpha
- CGPROGRAM
-
- #pragma vertex Vert
- #pragma fragment Frag
- #include "UnityCG.cginc"
-
- float _Tiling;
- float _WaveSpeed;
- float _SpecularRatio;
- sampler2D _WaterTex;
- sampler2D _WaterTex2;
- sampler2D _ReflectionTex;
- float4 _LightColorSelf;
- float4 _LightDir;
- float4 _BottomColor;
- float4 _TopColor;
- float _Alpha;
- float _ReflectionLight;
-
-
- struct v2f
- {
- float4 position : POSITION;
- float3 worldPos : TEXCOORD0;
- float3 tilingAndOffset:TEXCOORD2;
- float4 screen:TEXCOORD3;
- float4 VertColor :TEXCOORD4;
-
- };
-
-
-
-
-
-
-
- v2f Vert(appdata_full v)
- {
- v2f o;
- o.worldPos = mul(unity_ObjectToWorld, v.vertex);
- o.position = UnityObjectToClipPos(v.vertex);
- //uv动画
- o.tilingAndOffset.z =frac( _Time.x * _WaveSpeed);
- o.tilingAndOffset.xy = o.worldPos.xz*_Tiling;
- o.screen = ComputeScreenPos(o.position);
- o.VertColor = v.color;
- return o;
- }
-
-
-
- float4 Frag(v2f i):COLOR
- {
- float3 lightColor=_LightColorSelf.rgb*2;
- //世界视向量
- float3 worldView = -normalize(i.worldPos - _WorldSpaceCameraPos);
- float2 tiling = i.tilingAndOffset.xy;
- //法线采样
- float4 N1 = tex2D(_WaterTex, tiling.yx +float2(i.tilingAndOffset.z,0));
- float4 N2 = tex2D(_WaterTex2, tiling.yx -float2(i.tilingAndOffset.z,0));
- //两个法线相加,转世界空间,这里没有unpack,所以法线贴图不需要转normal 法线贴图为0-1 两张加起来为0-2 将其x2-2,转换为-2 --2然后将其normalize,变成-1到1
- //在遇到两张法线的情况下 ,一般将法线相加 再normalize
- float3 worldNormal = normalize((N1.xyz+N2.xyz)*2-2);
- //以垂直的方向代替灯光 跟法线做点积 得到漫反射强度
- float LdotN = dot(worldNormal, float3(0,1,0));
- fixed2 uv = i.screen.xy/(i.screen.w+0.0001);
- uv.y = 1-uv.y;
-
-
- fixed4 refTex = tex2D (_ReflectionTex,uv + worldNormal.xy*0.02 );
-
-
-
-
-
-
- //这个变量一般在Forward渲染路径下使用,存储的是重要的pixel光源方向,没错,的确是使用w来判断这个光源的类型的,一般和_LightColor0配合使用
- //float3 LView=_WorldSpaceLightPos0.xyz;
- float3 LView = _LightDir.xyz;
-
- //if(_WorldSpaceLightPos0.w == 0.0){
- // L = normalize(_WorldSpaceLightPos0.xyz);
- // }
- // else{
- // L = normalize(_WorldSpaceLightPos0.xyz - i.worldPos);
- // }
-
-
-
-
- //根据世界法线 ,世界视向量+光向量 得出高光 系数
- float dotSpecular = dot(worldNormal, normalize( worldView+LView));
- //控制高光的范围
- float3 specularReflection = pow(saturate(dotSpecular), _SpecularRatio);
-
-
-
-
- float4 col;
- float fresnel = 0.5*LdotN+0.5;
- //根据法线的强度 来确定两种颜色之间的混合 ????
- col.rgb = lerp(_BottomColor.xyz, _TopColor.xyz, fresnel);
-
- col.rgb = saturate (LdotN) *col.rgb;
-
-
- //加上高光
- col.rgb += specularReflection;
- col.rgb = lerp (col.rgb,refTex.rgb*_ReflectionLight,0.7);
- //col.rgb +=refTex.rgb*_ReflectionLight;
- //加上灯光颜色
- col.rgb*=lightColor;
- col.rgb *= i.VertColor.rgb;
- //控制透明度
-
- col.a =i.VertColor.a * _Alpha;
- return col;
- }
-
- ENDCG
- }
-
- }
-
- FallBack "Diffuse"
- }
2.c# 反射
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- [ExecuteInEditMode]
- public class ReflectionSelf : MonoBehaviour {
-
- private Transform refObject;
- private Camera m_camera;
- public LayerMask reflectionMask;
- private RenderTexture m_texture;
-
- void Start () {
- refObject = this.GetComponent<Transform>();
- GameObject refCramera = new GameObject("refCramera");
- m_camera = refCramera.AddComponent<Camera>();
- m_texture = new RenderTexture(Screen.width,Screen.height,24);
- refCameraSet();
- }
-
- /// <summary>
- /// 相机位置及方向
- /// </summary>
- void cameraTrasform()
- {
- //Position x z 与mainCamera相同 y 到平面的距离与 mainCamera到平面的距离相等
- Vector3 p_ref;
- Vector3 p_main = Camera.main.transform.position;
- Vector3 p_plan = this.transform.position;
- float y = p_main.y - p_plan.y;
-
- p_ref.x = p_main.x;
- p_ref.y = p_plan.y - y;
- p_ref.z = p_main.z;
- m_camera.transform.position = p_ref;
-
- //Rotation
- Vector3 R_ref;
- Vector3 R_main = Camera.main.transform.localEulerAngles;
-
- R_ref.x = -R_main.x;
- R_ref.y = R_main.y;
- R_ref.z = R_main.z;
- m_camera.transform.localEulerAngles = R_ref;
- }
-
- /// <summary>
- /// 反射相机的设置
- /// </summary>
-
- void refCameraSet()
- {
- m_camera.backgroundColor = Color.black;
- m_camera.clearFlags = CameraClearFlags.Skybox;
- m_camera.cullingMask = reflectionMask; //图层
- m_camera.targetTexture = m_texture;
- this.GetComponent<Renderer>().sharedMaterial.SetTexture("_ReflectionTex", m_camera.targetTexture);
- }
-
-
-
-
-
-
- void Update () {
- //相机位置要放在这里,因为要随着主相机一直运动
- cameraTrasform();
-
-
- }
- }
3.曾经在官方的demo里看到反射相机的写法 比较复杂 在此也贴出来 用这个脚本的话 需要把水的shader里面屏幕UV的y方向变为正方向
- using UnityEngine;
- using System.Collections.Generic;
- //[ExecuteInEditMode]
- public class ReflectionFx : MonoBehaviour
- {
- public Transform[] reflectiveObjects;
- public LayerMask reflectionMask;
- public Material[] reflectiveMaterials;
- private Transform reflectiveSurfaceHeight;
- public Shader replacementShader;
- private bool highQuality = false;
- public Color clearColor = Color.black;
- public System.String reflectionSampler = "_ReflectionTex";
-
- public float clipPlaneOffset = 0.07F;
- private Vector3 oldpos = Vector3.zero;
- //反射相机
- private Camera reflectionCamera;
- private Dictionary<Camera, bool> helperCameras = null;
- private Texture[] initialReflectionTextures;
- public void Start()
- {
- initialReflectionTextures = new Texture2D[reflectiveMaterials.Length];
- for (int i = 0; i < reflectiveMaterials.Length; i++)
- {
- initialReflectionTextures[i] = reflectiveMaterials[i].GetTexture(reflectionSampler);
- }
-
- this.enabled = true;
- }
- public void OnDisable()
- {
- if (initialReflectionTextures == null)
- return;
- // restore initial reflection textures
- for (int i = 0; i < reflectiveMaterials.Length; i++)
- {
- reflectiveMaterials[i].SetTexture(reflectionSampler, initialReflectionTextures[i]);
- }
- }
- //创建新相机
- private Camera CreateReflectionCameraFor(Camera cam)
- {
- //将string类初始化,挂脚本的物体名 + “Reflection” + 输入的cam名字
- System.String reflName = gameObject.name + "Reflection" + cam.name;
- //Debug.Log("AngryBots: created internal reflection camera " + reflName);
- //找到这个名字的物体,并将go 实例化
- GameObject go = GameObject.Find(reflName);
-
- if (!go) //如果这个物体不存在
- go = new GameObject(reflName, typeof(Camera)); //再重新创建一个新的物体,给他赋上名字和类型
- if (!go.GetComponent(typeof(Camera))) //这个物体没有Camera组件
- go.AddComponent(typeof(Camera));//给它加上Camera组件
- Camera reflectCamera = go.GetComponent<Camera>(); //reflectCamera实例化为这个物体(go)的相机组件
- reflectCamera.backgroundColor = clearColor; //相机的背景颜色 把背景色设置为clearColor 就不会遮盖住背后的视图
-
- reflectCamera.clearFlags = CameraClearFlags.Skybox;//清楚标记,SolidColor:屏幕上的任何空的部分将显示当前相机的背景颜色
- SetStandardCameraParameter(reflectCamera, reflectionMask);//设置渲染图层
-
- if (!reflectCamera.targetTexture) //如果反射相机没有targetTexture
- reflectCamera.targetTexture = CreateTextureFor(cam); //用这个方法创建targetTexture赋给相机的targetTexture
- return reflectCamera;
- }
- public void HighQuality()
- {
- highQuality = true;
- }
-
- //设置反射相机的渲染图层
- private void SetStandardCameraParameter(Camera cam, LayerMask mask)
- {
- cam.backgroundColor = Color.black; //背景色为黑色
- cam.enabled = true; //cam为false状态?
- cam.cullingMask = reflectionMask; //设置渲染图层
- }
- //给相机赋上targetTexture
- private RenderTexture CreateTextureFor(Camera cam)
- {
- RenderTextureFormat rtFormat = RenderTextureFormat.RGB565;
- if (!SystemInfo.SupportsRenderTextureFormat(rtFormat))
- rtFormat = RenderTextureFormat.Default;
- float rtSizeMul = highQuality ? 0.75f : 0.5f;
- RenderTexture rt = new RenderTexture(Mathf.FloorToInt(cam.pixelWidth * rtSizeMul), Mathf.FloorToInt(cam.pixelHeight * rtSizeMul), 24, rtFormat);
- rt.hideFlags = HideFlags.DontSave;
-
- return rt;
- }
- public void RenderHelpCameras(Camera currentCam)
- {
- if (null == helperCameras)
- helperCameras = new Dictionary<Camera, bool>();
- if (!helperCameras.ContainsKey(currentCam))
- {
- helperCameras.Add(currentCam, false);
- }
- if (helperCameras[currentCam])
- {
- return;
- }
- if (!reflectionCamera)
- {
- reflectionCamera = CreateReflectionCameraFor(currentCam);
- foreach (Material m in reflectiveMaterials)
- {
- m.SetTexture(reflectionSampler, reflectionCamera.targetTexture);
- }
- }
- RenderReflectionFor(currentCam, reflectionCamera);
- helperCameras[currentCam] = true;
- }
- public void LateUpdate()
- {
- // find the closest reflective surface and use that as our
- // reference for reflection height etc.
- //找到最接近的反射面并将其作为我们的
- //参考高度等。
- Transform closest = null;
- float closestDist = Mathf.Infinity;
- Vector3 pos = Camera.main.transform.position;
- foreach (Transform t in reflectiveObjects)
- {
- if (t.GetComponent<Renderer>().isVisible)
- {
- float dist = (pos - t.position).sqrMagnitude;
- if (dist < closestDist)
- {
- closestDist = dist;
- closest = t;
- }
- }
- }
- if (!closest)
- return;
- ObjectBeingRendered(closest, Camera.main);
- if (null != helperCameras)
- helperCameras.Clear();
- }
- private void ObjectBeingRendered(Transform tr, Camera currentCam)
- {
- if (null == tr)
- return;
- reflectiveSurfaceHeight = tr;
- RenderHelpCameras(currentCam);
- }
- private void RenderReflectionFor(Camera cam, Camera reflectCamera)
- {
- if (!reflectCamera)
- return;
- SaneCameraSettings(reflectCamera);
- reflectCamera.backgroundColor = clearColor;
- //GL.SetRevertBackfacing(true);
- GL.invertCulling = true;
- Transform reflectiveSurface = reflectiveSurfaceHeight;
- Vector3 eulerA = cam.transform.eulerAngles;
- reflectCamera.transform.eulerAngles = new Vector3(-eulerA.x, eulerA.y, eulerA.z);
- reflectCamera.transform.position = cam.transform.position;
- Vector3 pos = reflectiveSurface.transform.position;
- pos.y = reflectiveSurface.position.y;
- Vector3 normal = reflectiveSurface.transform.up;
- float d = -Vector3.Dot(normal, pos) - clipPlaneOffset;
- Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
- Matrix4x4 reflection = Matrix4x4.zero;
- reflection = CalculateReflectionMatrix(reflection, reflectionPlane);
- oldpos = cam.transform.position;
- Vector3 newpos = reflection.MultiplyPoint(oldpos);
- reflectCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
- Vector4 clipPlane = CameraSpacePlane(reflectCamera, pos, normal, 1.0f);
- Matrix4x4 projection = cam.projectionMatrix;
- projection = CalculateObliqueMatrix(projection, clipPlane);
- reflectCamera.projectionMatrix = projection;
- reflectCamera.transform.position = newpos;
- Vector3 euler = cam.transform.eulerAngles;
- reflectCamera.transform.eulerAngles = new Vector3(-euler.x, euler.y, euler.z);
-
- reflectCamera.RenderWithShader(replacementShader, "Reflection");
- //GL.SetRevertBackfacing(false);
- GL.invertCulling = false;
- }
- private void SaneCameraSettings(Camera helperCam)
- {
- helperCam.depthTextureMode = DepthTextureMode.None;
- helperCam.backgroundColor = Color.black;
- helperCam.clearFlags = CameraClearFlags.Skybox;
- helperCam.renderingPath = RenderingPath.Forward;
- }
- static Matrix4x4 CalculateObliqueMatrix(Matrix4x4 projection, Vector4 clipPlane)
- {
- Vector4 q = projection.inverse * new Vector4(
- 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];
- return projection;
- }
-
- // Helper function for getting the reflection matrix that will be multiplied with camera matrix
- //用摄像机矩阵来得到反射矩阵的辅助函数
- static Matrix4x4 CalculateReflectionMatrix(Matrix4x4 reflectionMat, Vector4 plane)
- {
- reflectionMat.m00 = (1.0F - 2.0F * plane[0] * plane[0]);
- reflectionMat.m01 = (-2.0F * plane[0] * plane[1]);
- reflectionMat.m02 = (-2.0F * plane[0] * plane[2]);
- reflectionMat.m03 = (-2.0F * plane[3] * plane[0]);
- reflectionMat.m10 = (-2.0F * plane[1] * plane[0]);
- reflectionMat.m11 = (1.0F - 2.0F * plane[1] * plane[1]);
- reflectionMat.m12 = (-2.0F * plane[1] * plane[2]);
- reflectionMat.m13 = (-2.0F * plane[3] * plane[1]);
- reflectionMat.m20 = (-2.0F * plane[2] * plane[0]);
- reflectionMat.m21 = (-2.0F * plane[2] * plane[1]);
- reflectionMat.m22 = (1.0F - 2.0F * plane[2] * plane[2]);
- reflectionMat.m23 = (-2.0F * plane[3] * plane[2]);
- reflectionMat.m30 = 0.0F;
- reflectionMat.m31 = 0.0F;
- reflectionMat.m32 = 0.0F;
- reflectionMat.m33 = 1.0F;
-
- return reflectionMat;
- }
- // Extended sign: returns -1, 0 or 1 based on sign of a
- //扩展符号:返回-1、0或1,基于a的符号
- static float sgn(float a)
- {
- if (a > 0.0F) return 1.0F;
- if (a < 0.0F) return -1.0F;
- return 0.0F;
- }
- // Given position/normal of the plane, calculates plane in camera space.
- //给定平面的正/正态,在相机空间计算平面
- private Vector4 CameraSpacePlane(Camera cam, Vector3 pos, Vector3 normal, float sideSign)
- {
- Vector3 offsetPos = pos + normal * clipPlaneOffset;
- Matrix4x4 m = cam.worldToCameraMatrix;
- Vector3 cpos = m.MultiplyPoint(offsetPos);
- Vector3 cnormal = m.MultiplyVector(normal).normalized * sideSign;
- return new Vector4(cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos, cnormal));
- }
- }
亲,如果您觉得本文不错,愿意给我一些动力的话,请用手机扫描二维码即可向我打赏
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。