private void UpdateCameraMatrix() { Vector3 dir = mirrorCamera.transform.position - transform.position; var up = Vector3.Cross(-dir, mirrorCamera.transform.right); mirrorCamera.transform.rotation = Quaternion.LookRotation(-dir, up); Vector4 clipplane = CameraHelper.CameraSpacePlane(mirrorCamera, transform.position, transform.forward, 0.01f); Matrix4x4 clipP = mirrorCamera.projectionMatrix; CameraHelper.CalculateObliqueMatrix(ref clipP, clipplane); mirrorCamera.projectionMatrix = clipP; }
void RenderReflectionAndRefraction() { Camera renderCamera = Camera.mainCamera; Matrix4x4 originalWorldToCam = renderCamera.worldToCameraMatrix; int cullingMask = ~(1 << 4) & renderLayers.value; ; //Reflection pass Matrix4x4 reflection = Matrix4x4.zero; //TODO: Use local plane here, not global! float d = -transform.position.y; offscreenCam.backgroundColor = RenderSettings.fogColor; CameraHelper.CalculateReflectionMatrix(ref reflection, new Vector4(0f, 1f, 0f, d)); offscreenCam.transform.position = reflection.MultiplyPoint(renderCamera.transform.position); offscreenCam.transform.rotation = renderCamera.transform.rotation; offscreenCam.worldToCameraMatrix = originalWorldToCam * reflection; offscreenCam.cullingMask = cullingMask; offscreenCam.targetTexture = reflectionTexture; //Need to reverse face culling for reflection pass, since the camera //is now flipped upside/down. GL.SetRevertBackfacing(true); Vector4 cameraSpaceClipPlane = CameraHelper.CameraSpacePlane(offscreenCam, new Vector3(0.0f, transform.position.y, 0.0f), Vector3.up, 1.0f); Matrix4x4 projection = renderCamera.projectionMatrix; Matrix4x4 obliqueProjection = projection; offscreenCam.fieldOfView = renderCamera.fieldOfView; offscreenCam.aspect = renderCamera.aspect; CameraHelper.CalculateObliqueMatrix(ref obliqueProjection, cameraSpaceClipPlane); //Do the actual render, with the near plane set as the clipping plane. See the //pro water source for details. offscreenCam.projectionMatrix = obliqueProjection; if (!renderReflection) { offscreenCam.cullingMask = 0; } offscreenCam.Render(); GL.SetRevertBackfacing(false); //Refractionpass //TODO: If we want to use this as a refraction seen from under the seaplane, // the cameraclear should be skybox. offscreenCam.cullingMask = cullingMask; offscreenCam.targetTexture = refractionTexture; obliqueProjection = projection; offscreenCam.transform.position = renderCamera.transform.position; offscreenCam.transform.rotation = renderCamera.transform.rotation; offscreenCam.worldToCameraMatrix = originalWorldToCam; cameraSpaceClipPlane = CameraHelper.CameraSpacePlane(offscreenCam, Vector3.zero, Vector3.up, -1.0f); CameraHelper.CalculateObliqueMatrix(ref obliqueProjection, cameraSpaceClipPlane); offscreenCam.projectionMatrix = obliqueProjection; //if (!renderRefraction) //offscreenCam.cullingMask = 0; offscreenCam.Render(); offscreenCam.projectionMatrix = projection; offscreenCam.targetTexture = null; }
void RenderReflectionAndRefraction() { //return; //camera.ResetWorldToCameraMatrix(); offscreenCam.enabled = true; int oldPixelLightCount = QualitySettings.pixelLightCount; QualitySettings.pixelLightCount = 0; Camera renderCamera = mycam; Matrix4x4 originalWorldToCam = renderCamera.worldToCameraMatrix; int cullingMask = renderCamera.cullingMask & ~(1 << LayerMask.NameToLayer("Water")); //Reflection pass Matrix4x4 reflection = Matrix4x4.zero; //TODO: Use local plane here, not global! CameraHelper.CalculateReflectionMatrix(ref reflection, new Vector4(0.0f, 1.0f, 0.0f, 0.0f)); offscreenCam.transform.position = reflection.MultiplyPoint(renderCamera.transform.position); offscreenCam.transform.rotation = renderCamera.transform.rotation; offscreenCam.transform.Rotate(0, 180, 0); offscreenCam.worldToCameraMatrix = originalWorldToCam * reflection; offscreenCam.cullingMask = cullingMask; offscreenCam.targetTexture = reflectionTexture; offscreenCam.clearFlags = renderCamera.clearFlags; //Need to reverse face culling for reflection pass, since the camera //is now flipped upside/down. GL.SetRevertBackfacing(false); Vector4 cameraSpaceClipPlane = CameraHelper.CameraSpacePlane(offscreenCam, Vector3.zero, Vector3.up, 1.0f); Matrix4x4 projection = renderCamera.projectionMatrix; Matrix4x4 obliqueProjection = projection; CameraHelper.CalculateObliqueMatrix(ref obliqueProjection, cameraSpaceClipPlane); //Do the actual render, with the near plane set as the clipping plane. See the //pro water source for details. offscreenCam.projectionMatrix = obliqueProjection; offscreenCam.Render(); GL.SetRevertBackfacing(false); //Refractionpass bool fog = RenderSettings.fog; Color fogColor = RenderSettings.fogColor; float fogDensity = RenderSettings.fogDensity; RenderSettings.fog = true; RenderSettings.fogColor = Color.grey; RenderSettings.fogDensity = waterDirtyness / 10; //TODO: If we want to use this as a refraction seen from under the seaplane, // the cameraclear should be skybox. offscreenCam.clearFlags = CameraClearFlags.Color; offscreenCam.backgroundColor = Color.grey; offscreenCam.targetTexture = refractionTexture; obliqueProjection = projection; offscreenCam.transform.position = renderCamera.transform.position; offscreenCam.transform.rotation = renderCamera.transform.rotation; offscreenCam.worldToCameraMatrix = originalWorldToCam; cameraSpaceClipPlane = CameraHelper.CameraSpacePlane(offscreenCam, Vector3.zero, Vector3.up, -1.0f); CameraHelper.CalculateObliqueMatrix(ref obliqueProjection, cameraSpaceClipPlane); offscreenCam.projectionMatrix = obliqueProjection; offscreenCam.Render(); RenderSettings.fog = fog; RenderSettings.fogColor = fogColor; RenderSettings.fogDensity = fogDensity; offscreenCam.projectionMatrix = projection; offscreenCam.targetTexture = null; QualitySettings.pixelLightCount = oldPixelLightCount; // camera.ResetWorldToCameraMatrix(); //GL.SetRevertBackfacing (true); }
public void CalculateCameraMatrix(BoxCollider Box, Camera cam, bool bleft = true) { Vector3 dir = stereoCameraHead.transform.position - Box.transform.position; //dl -> dr -> ur -> rl clockwise points = Box.GetMinProjectBox(ref dir);// new Vector3[] {dl, dr, ur, ul }; Debug.DrawLine(cam.transform.position - dir, cam.transform.position, Color.yellow); Vector3 vecLeft, vecRight; Vector3 cameraUp = Vector3.up; float aspect = 0; for (int i = 0; i < 4; i++) { int iLeft = (i - 1 + 4) % 4; int iRight = (i + 1) % 4; vecLeft = points[iLeft] - points[i]; vecRight = points[iRight] - points[i]; float angle = Vector3.Angle(vecLeft, vecRight); if (angle < 90) { continue; } float lenLeft = vecLeft.magnitude; float lenRight = vecRight.magnitude; if (lenLeft > lenRight) { Vector3 vec = Vector3.Project(vecRight, vecLeft); points[i] = points[i] + vec; points[(i + 2) % 4] -= vec; cameraUp = points[iRight] - points[i]; vec = points[iLeft] - points[i]; aspect = vec.magnitude / cameraUp.magnitude; } else { Vector3 vec = Vector3.Project(vecLeft, vecRight); points[i] = points[i] + vec; points[(i + 2) % 4] -= vec; cameraUp = points[iLeft] - points[i]; vec = points[iRight] - points[i]; aspect = vec.magnitude / cameraUp.magnitude; } break; } cam.transform.rotation = Quaternion.LookRotation(-dir, cameraUp); //cam.transform.LookAt(-dir, cameraUp); //Vector3 vecDLtoDR = dl - dr; //Vector3 vecURtoDR = ur - dr; //float lenDLtoDR = vecDLtoDR.magnitude; //float lenURtoDR = vecURtoDR.magnitude; //if (lenDLtoDR > lenURtoDR) //{ // //base edge vecDLtoDR float fov = Mathf.Atan2(cameraUp.magnitude / 2, dir.magnitude) * 180 / Mathf.PI; cam.fieldOfView = fov * 2; cam.aspect = aspect; Matrix4x4 P = Matrix4x4.Perspective(fov * 2, aspect, 0.1f, 1000); Vector4 clipplane = CameraHelper.CameraSpacePlane(cam, Box.transform.position, -Box.transform.forward, 0.01f); Matrix4x4 clipP = P; CameraHelper.CalculateObliqueMatrix(ref clipP, clipplane); ///Matrix4x4 mat = Camera.main.projectionMatrix; cam.projectionMatrix = clipP; // = Camera.main.CalculateObliqueMatrix(clipplane); //calculate the mirror camera's vp //var mirrorVPMat = mat * Camera.main.worldToCameraMatrix; //var mirrorVPMat = mat.transpose;// * Camera.main.worldToCameraMatrix; Matrix4x4 V = cam.worldToCameraMatrix; P = GL.GetGPUProjectionMatrix(P, true); Matrix4x4 VP = P * V; if (bleft) { Box.GetComponentInChildren <Renderer>().material.SetVector("_matrix01", new Vector4(VP.m00, VP.m01, VP.m02, VP.m03)); Box.GetComponentInChildren <Renderer>().material.SetVector("_matrix02", new Vector4(VP.m10, VP.m11, VP.m12, VP.m13)); Box.GetComponentInChildren <Renderer>().material.SetVector("_matrix03", new Vector4(VP.m20, VP.m21, VP.m22, VP.m23)); Box.GetComponentInChildren <Renderer>().material.SetVector("_matrix04", new Vector4(VP.m30, VP.m31, VP.m32, VP.m33)); } else { Box.GetComponentInChildren <Renderer>().material.SetVector("_rmatrix01", new Vector4(VP.m00, VP.m01, VP.m02, VP.m03)); Box.GetComponentInChildren <Renderer>().material.SetVector("_rmatrix02", new Vector4(VP.m10, VP.m11, VP.m12, VP.m13)); Box.GetComponentInChildren <Renderer>().material.SetVector("_rmatrix03", new Vector4(VP.m20, VP.m21, VP.m22, VP.m23)); Box.GetComponentInChildren <Renderer>().material.SetVector("_rmatrix04", new Vector4(VP.m30, VP.m31, VP.m32, VP.m33)); } Box.GetComponentInChildren <Renderer>().material.SetFloat("_depth", dir.magnitude - 0.1f); }
// 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() { var rend = GetComponent <Renderer>(); if (!enabled || !rend || !rend.sharedMaterial || !rend.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; UpdateCameraModes(cam, reflectionCamera); // Render reflection // Reflect camera around reflection plane float d = -Vector3.Dot(normal, pos) - m_ClipPlaneOffset; Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d); Matrix4x4 reflection = Matrix4x4.zero; CameraHelper.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 = CameraHelper.CameraSpacePlane(reflectionCamera, pos, normal, 1.0f); //Matrix4x4 projection = cam.projectionMatrix; //Matrix4x4 projection = cam.CalculateObliqueMatrix(clipPlane); Matrix4x4 clipP = reflectionCamera.projectionMatrix; CameraHelper.CalculateObliqueMatrix(ref clipP, clipPlane); reflectionCamera.projectionMatrix = clipP; 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 = new Vector3(0, euler.y, euler.z); reflectionCamera.Render(); //reflectionCamera.transform.position = oldpos; GL.SetRevertBackfacing(false); Material[] materials = rend.sharedMaterials; foreach (Material mat in materials) { if (mat.HasProperty("_ReflectionTex")) { mat.SetTexture("_ReflectionTex", m_ReflectionTexture); } } // Restore pixel light count s_InsideRendering = false; }