Main reference standard Asset of the water specular reflection of the idea
private static bool S_insidewater = FALSE;
Private Rendertexture m_reflectiontexture; Private Dictionary<camera, camera> M_reflectioncameras = new Dictionary<camera, camera> ();
Camera---camera table public float clipplaneoffset = 0.07f;
public int texturesize = 256;
Public Layermask reflectlayers =-1;
public void Onwillrenderobject () {Camera Currentcamera = camera.current;
Camera Currentcamera = Camera.main;
if (!currentcamera) {return;
} if (S_insidewater) {return;
} S_insidewater = true;
if (!m_reflectiontexture) {m_reflectiontexture = new Rendertexture (texturesize, Texturesize, 16);
M_reflectiontexture.name = "__waterreflection" + Getinstanceid ();
M_reflectiontexture.ispoweroftwo = true;
M_reflectiontexture.hideflags = Hideflags.dontsave; }
Camera Reflectioncamera;
Camera for Reflection M_reflectioncameras.trygetvalue (Currentcamera, out Reflectioncamera); if (!reflectioncamera)//Catch both Not-in-dictionary and in-dictionary-but-deleted-go {//gameobject Go = new Gameobject ("Water refl Camera ID" + getinstanceid () + "for" + Currentcamera.getinstanceid (), typeof (camera), t
Ypeof (Skybox)); Gameobject go = new Gameobject ("Water refl Camera ID" + getinstanceid () + "for" + Currentcamera.getinstanceid (), typeof (
Camera)); Reflectioncamera = go.
Getcomponent<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
Reflectioncamera.clearflags = Currentcamera.clearflags;
Reflectioncamera.backgroundcolor = Currentcamera.backgroundcolor;
Reflectioncamera.clearflags = Cameraclearflags.solidcolor;
Reflectioncamera.backgroundcolor = new Color (0, 0, 0, 0);
Update other values to match the current camera.
Reflectioncamera.farclipplane = Currentcamera.farclipplane;
Reflectioncamera.nearclipplane = Currentcamera.nearclipplane;
Reflectioncamera.orthographic = currentcamera.orthographic;
Reflectioncamera.fieldofview = Currentcamera.fieldofview;
Reflectioncamera.aspect = Currentcamera.aspect;
Reflectioncamera.orthographicsize = currentcamera.orthographicsize;
}//Find out the reflection plane:position and normal in world space Vector3 pos = transform.position;
Vector3 normal = Transform.up; 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 = Matrix4x4.zero;
Calculatereflectionmatrix (ref reflection, Reflectionplane);
Vector3 oldpos = currentCamera.transform.position; Vector3 Newpos = Reflection.
Multiplypoint (Oldpos);
Reflectioncamera.worldtocameramatrix = Currentcamera.worldtocameramatrix * reflection; Setup Oblique projection matrix So, near plane are our reflection//plane.
This is the We clip everything below/above it for free.
Vector4 Clipplane = Cameraspaceplane (Reflectioncamera, POS, Normal, 1.0f);
Calculates and returns oblique Near-plane projection matrix.
Reflectioncamera.projectionmatrix = Reflectioncamera.calculateobliquematrix (Clipplane); Never render water layer//reflectioncamera.cullingMask = ~ (1 << 4) & Reflectlayers.value;
Reflectioncamera.cullingmask = ~ (1 << reflectlayers.value);
Reflectioncamera.targettexture = m_reflectiontexture;
Select whether to invert the backface culling (true) or not (false).
Gl.invertculling = true;
ReflectionCamera.transform.position = Newpos;
Vector3 Euler = currentCamera.transform.eulerAngles;
ReflectionCamera.transform.eulerAngles = new Vector3 (-euler.x, Euler.y, Euler.z);
Reflectioncamera.render ();
ReflectionCamera.transform.position = Oldpos;
Gl.invertculling = false;
Getcomponent<renderer> (). Sharedmaterial.settexture ("_reflectiontex", m_reflectiontexture);
S_insidewater = false;
}//Transform the Pos,normal plane into view, (normal should be the inverse matrix!!!!!!!!!!!) 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)); } static void 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; } void Ondisable () {if (m_reflectiontexture) {destroyimmediate (m_reflectiontexture)
;
M_reflectiontexture = null; } foreach (Var kvp in M_reflectioncameras) {destroyimmediate ((kvp.
Value). Gameobject);
} m_reflectioncameras.clear (); }
The corresponding _reflectiontex is obtained in the shader, then the related operation can be carried out.
For example:
. vert file:
O.uv_ref = Computescreenpos (O.pos);
. frag File:
Half4 Refl_col = tex2dproj (_reflectiontex, Unity_proj_coord (uv_ref));
Finalcolor.rgb = Lerp (Finalcolor.rgb, Refl_col.rgb, REFL_COL.A);