protected override void InitNode() { Body = GetComponentInParent <CelestialBody>(); Body.TerrainNodes.Add(this); TerrainMaterial = MaterialHelper.CreateTemp(Body.ColorShader, "TerrainNode"); //Manager.GetSkyNode().InitUniforms(TerrainMaterial); var faces = new Vector3d[] { new Vector3d(0, 0, 0), new Vector3d(90, 0, 0), new Vector3d(90, 90, 0), new Vector3d(90, 180, 0), new Vector3d(90, 270, 0), new Vector3d(0, 180, 180) }; FaceToLocal = Matrix4x4d.Identity(); // If this terrain is deformed into a sphere the face matrix is the rotation of the // terrain needed to make up the spherical planet. In this case there should be 6 terrains, each with a unique face number if (Face - 1 >= 0 && Face - 1 < 6) { FaceToLocal = Matrix4x4d.Rotate(faces[Face - 1]); } //LocalToWorld = Matrix4x4d.ToMatrix4x4d(transform.localToWorldMatrix) * FaceToLocal; LocalToWorld = FaceToLocal; Deformation = new DeformationSpherical(Body.Radius); TerrainQuadRoot = new TerrainQuad(this, null, 0, 0, -Body.Radius, -Body.Radius, 2.0 * Body.Radius, ZMin, ZMax); }
// Use this for initialization protected virtual void Start() { m_worldToCameraMatrix = Matrix4x4d.Identity(); m_cameraToWorldMatrix = Matrix4x4d.Identity(); m_cameraToScreenMatrix = Matrix4x4d.Identity(); m_screenToCameraMatrix = Matrix4x4d.Identity(); m_worldCameraPos = new Vector3d2(); m_cameraDir = new Vector3d2(); m_worldPos = new Vector3d2(); Constrain(); }
protected override void InitNode() { OceanMaterial = MaterialHelper.CreateTemp(OceanShader, "Ocean"); planetoid.Atmosphere.InitUniforms(OceanMaterial); OldLocalToOcean = Matrix4x4d.Identity(); Offset = Vector4.zero; // Create the projected grid. The resolution is the size in pixels of each square in the grid. // If the squares are small the size of the mesh will exceed the max verts for a mesh in Unity. In this case split the mesh up into smaller meshes. Resolution = Mathf.Max(1, Resolution); // The number of squares in the grid on the x and y axis var NX = Screen.width / Resolution; var NY = Screen.height / Resolution; var numGrids = 1; const int MAX_VERTS = 65000; // The number of meshes need to make a grid of this resolution if (NX * NY > MAX_VERTS) { numGrids += (NX * NY) / MAX_VERTS; } ScreenMeshGrids = new Mesh[numGrids]; // Make the meshes. The end product will be a grid of verts that cover the screen on the x and y axis with the z depth at 0. // This grid is then projected as the ocean by the shader for (int i = 0; i < numGrids; i++) { NY = Screen.height / numGrids / Resolution; ScreenMeshGrids[i] = MeshFactory.MakeOceanPlane(NX, NY, (float)i / (float)numGrids, 1.0f / (float)numGrids); ScreenMeshGrids[i].bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); } }
public override Matrix4x4d LocalToDeformedDifferential(Vector3d localPoint, bool clamp = false) { if (!MathUtility.IsFinite(localPoint.x) || !MathUtility.IsFinite(localPoint.y) || !MathUtility.IsFinite(localPoint.z)) { return(Matrix4x4d.Identity()); } var point = new Vector3d(localPoint); if (clamp) { point.x = point.x - Math.Floor((point.x + R) / (2.0 * R)) * 2.0 * R; point.y = point.y - Math.Floor((point.y + R) / (2.0 * R)) * 2.0 * R; } var l = point.x * point.x + point.y * point.y + R * R; var c0 = 1.0 / Math.Sqrt(l); var c1 = c0 * R / l; return(new Matrix4x4d((point.y * point.y + R * R) * c1, -point.x * point.y * c1, point.x * c0, R * point.x * c0, -point.x * point.y * c1, (point.x * point.x + R * R) * c1, point.y * c0, R * point.y * c0, -point.x * R * c1, -point.y * R * c1, R * c0, (R * R) * c0, 0.0, 0.0, 0.0, 1.0)); }
public override Matrix4x4d LocalToDeformedDifferential(Vector3d2 localPt, bool clamp = false) { if (!MathUtility.IsFinite(localPt.x) || !MathUtility.IsFinite(localPt.y) || !MathUtility.IsFinite(localPt.z)) { return(Matrix4x4d.Identity()); } Vector3d2 pt = new Vector3d2(localPt); if (clamp) { pt.x = pt.x - Math.Floor((pt.x + R) / (2.0 * R)) * 2.0 * R; pt.y = pt.y - Math.Floor((pt.y + R) / (2.0 * R)) * 2.0 * R; } double l = pt.x * pt.x + pt.y * pt.y + R * R; double c0 = 1.0 / Math.Sqrt(l); double c1 = c0 * R / l; return(new Matrix4x4d((pt.y * pt.y + R * R) * c1, -pt.x * pt.y * c1, pt.x * c0, R * pt.x * c0, -pt.x * pt.y * c1, (pt.x * pt.x + R * R) * c1, pt.y * c0, R * pt.y * c0, -pt.x * R * c1, -pt.y * R * c1, R * c0, (R * R) * c0, 0.0, 0.0, 0.0, 1.0)); }
public void updateCameraSpecificUniforms(Material oceanMaterial, Camera inCamera) { cameraToScreen = GL.GetGPUProjectionMatrix(inCamera.projectionMatrix, false); screenToCamera = cameraToScreen.inverse; m_oceanMaterial.SetMatrix("_Globals_CameraToScreen", cameraToScreen); m_oceanMaterial.SetMatrix("_Globals_ScreenToCamera", screenToCamera); //Calculates the required data for the projected grid // compute ltoo = localToOcean transform, where ocean frame = tangent space at // camera projection on sphere radius in local space //move these to dedicated projected grid class? Matrix4x4 ctol1 = inCamera.cameraToWorldMatrix; Matrix4x4d cameraToWorld = new Matrix4x4d(ctol1.m00, ctol1.m01, ctol1.m02, ctol1.m03, ctol1.m10, ctol1.m11, ctol1.m12, ctol1.m13, ctol1.m20, ctol1.m21, ctol1.m22, ctol1.m23, ctol1.m30, ctol1.m31, ctol1.m32, ctol1.m33); Vector3d translation = m_manager.parentLocalTransform.position; Matrix4x4d worldToLocal = new Matrix4x4d(1, 0, 0, -translation.x, 0, 1, 0, -translation.y, 0, 0, 1, -translation.z, 0, 0, 0, 1); Matrix4x4d camToLocal = worldToLocal * cameraToWorld; Matrix4x4d localToCam = camToLocal.Inverse(); // camera in local space relative to planet's origin Vector3d2 cl = new Vector3d2(); cl = camToLocal * Vector3d2.Zero(); double radius = m_manager.GetRadius(); uz = cl.Normalized(); // unit z vector of ocean frame, in local space if (m_oldlocalToOcean != Matrix4x4d.Identity()) { ux = (new Vector3d2(m_oldlocalToOcean.m [1, 0], m_oldlocalToOcean.m [1, 1], m_oldlocalToOcean.m [1, 2])).Cross(uz).Normalized(); } else { ux = Vector3d2.UnitZ().Cross(uz).Normalized(); } uy = uz.Cross(ux); // unit y vector oo = uz * (radius); // origin of ocean frame, in local space //local to ocean transform //computed from oo and ux, uy, uz should be correct Matrix4x4d localToOcean = new Matrix4x4d( ux.x, ux.y, ux.z, -ux.Dot(oo), uy.x, uy.y, uy.z, -uy.Dot(oo), uz.x, uz.y, uz.z, -uz.Dot(oo), 0.0, 0.0, 0.0, 1.0); Matrix4x4d cameraToOcean = localToOcean * camToLocal; Matrix4x4d worldToOcean = localToOcean * worldToLocal; Vector3d2 delta = new Vector3d2(0, 0, 0); if (m_oldlocalToOcean != Matrix4x4d.Identity()) { delta = localToOcean * (m_oldlocalToOcean.Inverse() * Vector3d2.Zero()); m_offset += delta; } //reset offset when bigger than 20000 to avoid floating point issues when later casting the offset to float if (Mathf.Max(Mathf.Abs((float)m_offset.x), Mathf.Abs((float)m_offset.y)) > 20000f) { m_offset.x = 0.0; m_offset.y = 0.0; } m_oldlocalToOcean = localToOcean; // Matrix4x4d ctos = ModifiedProjectionMatrix (inCamera); //moved to command buffer // Matrix4x4d stoc = ctos.Inverse (); Vector3d2 oc = cameraToOcean * Vector3d2.Zero(); h = oc.z; offset = new Vector3d2(-m_offset.x, -m_offset.y, h); //old horizon code //This breaks down when you tilt the camera by 90 degrees in any direction //I made some new horizon code down, scroll down // Vector4d stoc_w = (stoc * Vector4d.UnitW ()).XYZ0 (); // Vector4d stoc_x = (stoc * Vector4d.UnitX ()).XYZ0 (); // Vector4d stoc_y = (stoc * Vector4d.UnitY ()).XYZ0 (); // // Vector3d2 A0 = (cameraToOcean * stoc_w).XYZ (); // Vector3d2 dA = (cameraToOcean * stoc_x).XYZ (); // Vector3d2 B = (cameraToOcean * stoc_y).XYZ (); // // Vector3d2 horizon1, horizon2; // // double h1 = h * (h + 2.0 * radius); // double h2 = (h + radius) * (h + radius); // double alpha = B.Dot (B) * h1 - B.z * B.z * h2; // // double beta0 = (A0.Dot (B) * h1 - B.z * A0.z * h2) / alpha; // double beta1 = (dA.Dot (B) * h1 - B.z * dA.z * h2) / alpha; // // double gamma0 = (A0.Dot (A0) * h1 - A0.z * A0.z * h2) / alpha; // double gamma1 = (A0.Dot (dA) * h1 - A0.z * dA.z * h2) / alpha; // double gamma2 = (dA.Dot (dA) * h1 - dA.z * dA.z * h2) / alpha; // // horizon1 = new Vector3d2 (-beta0, -beta1, 0.0); // horizon2 = new Vector3d2 (beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2); Vector3d2 sunDir = new Vector3d2(m_manager.getDirectionToSun().normalized); Vector3d2 oceanSunDir = localToOcean.ToMatrix3x3d() * sunDir; oceanMaterial.SetMatrix(ShaderProperties._Globals_CameraToWorld_PROPERTY, cameraToWorld.ToMatrix4x4()); oceanMaterial.SetVector(ShaderProperties._Ocean_SunDir_PROPERTY, oceanSunDir.ToVector3()); oceanMaterial.SetMatrix(ShaderProperties._Ocean_CameraToOcean_PROPERTY, cameraToOcean.ToMatrix4x4()); oceanMaterial.SetMatrix(ShaderProperties._Ocean_OceanToCamera_PROPERTY, cameraToOcean.Inverse().ToMatrix4x4()); // oceanMaterial.SetMatrix (ShaderProperties._Globals_CameraToScreen_PROPERTY, ctos.ToMatrix4x4 ()); // oceanMaterial.SetMatrix (ShaderProperties._Globals_ScreenToCamera_PROPERTY, stoc.ToMatrix4x4 ()); oceanMaterial.SetMatrix(ShaderProperties._Globals_WorldToOcean_PROPERTY, worldToOcean.ToMatrix4x4()); oceanMaterial.SetMatrix(ShaderProperties._Globals_OceanToWorld_PROPERTY, worldToOcean.Inverse().ToMatrix4x4()); oceanMaterial.SetVector(ShaderProperties._Ocean_CameraPos_PROPERTY, offset.ToVector3()); //horizon calculations //these are used to find where the horizon line is on screen //and "clamp" vertexes that are above it back to it //as the grid is projected on the whole screen, vertexes over the horizon need to be dealt with //simply passing a flag to drop fragments or moving these vertexes offscreen will cause issues //as the horizon line can be between two vertexes and the horizon line will appear "pixelated" //as whole chunks go missing //these need to be done here //1)for double precision //2)for speed Vector3d2 sphereDir = localToCam * Vector3d2.Zero(); //vector to center of planet double OHL = sphereDir.Magnitude(); //distance to center of planet sphereDir = sphereDir.Normalized(); //direction to center of planet double rHorizon = Math.Sqrt((OHL)*(OHL)-(radius * radius)); //distance to the horizon, i.e distance to ocean sphere tangent //basic geometry yo //Theta=angle to horizon, now all that is left to do is check the viewdir against this angle in the shader double cosTheta = rHorizon / (OHL); double sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); oceanMaterial.SetVector(ShaderProperties.sphereDir_PROPERTY, sphereDir.ToVector3()); oceanMaterial.SetFloat(ShaderProperties.cosTheta_PROPERTY, (float)cosTheta); oceanMaterial.SetFloat(ShaderProperties.sinTheta_PROPERTY, (float)sinTheta); //planetshine properties if (Scatterer.Instance.mainSettings.usePlanetShine) { Matrix4x4 planetShineSourcesMatrix = m_manager.m_skyNode.planetShineSourcesMatrix; Vector3d2 oceanSunDir2; for (int i = 0; i < 4; i++) { Vector4 row = planetShineSourcesMatrix.GetRow(i); oceanSunDir2 = localToOcean.ToMatrix3x3d() * new Vector3d2(row.x, row.y, row.z); planetShineSourcesMatrix.SetRow(i, new Vector4((float)oceanSunDir2.x, (float)oceanSunDir2.y, (float)oceanSunDir2.z, row.w)); } oceanMaterial.SetMatrix("planetShineSources", planetShineSourcesMatrix); //this can become shared code to not recompute oceanMaterial.SetMatrix("planetShineRGB", m_manager.m_skyNode.planetShineRGBMatrix); } if (!ReferenceEquals(causticsShadowMaskModulator, null)) { causticsShadowMaskModulator.CausticsShadowMaskModulateMaterial.SetMatrix("CameraToWorld", inCamera.cameraToWorldMatrix); causticsShadowMaskModulator.CausticsShadowMaskModulateMaterial.SetMatrix("WorldToLight", Scatterer.Instance.sunLight.transform.worldToLocalMatrix); causticsShadowMaskModulator.CausticsShadowMaskModulateMaterial.SetVector("PlanetOrigin", m_manager.parentLocalTransform.position); float warpTime = (TimeWarp.CurrentRate > 1) ? (float)Planetarium.GetUniversalTime() : 0f; causticsShadowMaskModulator.CausticsShadowMaskModulateMaterial.SetFloat("warpTime", warpTime); } }
public void updateStuff(Material oceanMaterial, Camera inCamera) { //Calculates the required data for the projected grid // compute ltoo = localToOcean transform, where ocean frame = tangent space at // camera projection on sphere radius in local space Matrix4x4 ctol1 = inCamera.cameraToWorldMatrix; //position relative to kerbin // Vector3d tmp = (inCamera.transform.position) - m_manager.parentCelestialBody.transform.position; Matrix4x4d cameraToWorld = new Matrix4x4d(ctol1.m00, ctol1.m01, ctol1.m02, ctol1.m03, ctol1.m10, ctol1.m11, ctol1.m12, ctol1.m13, ctol1.m20, ctol1.m21, ctol1.m22, ctol1.m23, ctol1.m30, ctol1.m31, ctol1.m32, ctol1.m33); //Looking back, I have no idea how I figured this crap out Vector4 translation = m_manager.parentCelestialBody.transform.worldToLocalMatrix.inverse.GetColumn(3); Matrix4x4d worldToLocal = new Matrix4x4d(1, 0, 0, -translation.x, 0, 1, 0, -translation.y, 0, 0, 1, -translation.z, 0, 0, 0, 1); Matrix4x4d camToLocal = worldToLocal * cameraToWorld; // camera in local space relative to planet's origin Vector3d2 cl = new Vector3d2(); cl = camToLocal * Vector3d2.Zero(); // double radius = m_manager.GetRadius (); double radius = m_manager.GetRadius() + m_oceanLevel; // Vector3d2 ux, uy, uz, oo; uz = cl.Normalized(); // unit z vector of ocean frame, in local space if (m_oldlocalToOcean != Matrix4x4d.Identity()) { ux = (new Vector3d2(m_oldlocalToOcean.m [1, 0], m_oldlocalToOcean.m [1, 1], m_oldlocalToOcean.m [1, 2])).Cross(uz).Normalized(); } else { ux = Vector3d2.UnitZ().Cross(uz).Normalized(); } uy = uz.Cross(ux); // unit y vector oo = uz * (radius); // origin of ocean frame, in local space //local to ocean transform //computed from oo and ux, uy, uz should be correct Matrix4x4d localToOcean = new Matrix4x4d( ux.x, ux.y, ux.z, -ux.Dot(oo), uy.x, uy.y, uy.z, -uy.Dot(oo), uz.x, uz.y, uz.z, -uz.Dot(oo), 0.0, 0.0, 0.0, 1.0); Matrix4x4d cameraToOcean = localToOcean * camToLocal; //Couldn't figure out how to change the wind's direction in all that math so I tried to do the easy thing //And Rotated the ocean and the sun //This didn't work //deleted rotation code here Vector3d2 delta = new Vector3d2(0, 0, 0); if (m_oldlocalToOcean != Matrix4x4d.Identity()) { delta = localToOcean * (m_oldlocalToOcean.Inverse() * Vector3d2.Zero()); m_offset += delta; } m_oldlocalToOcean = localToOcean; Matrix4x4d ctos = ModifiedProjectionMatrix(inCamera); Matrix4x4d stoc = ctos.Inverse(); Vector3d2 oc = cameraToOcean * Vector3d2.Zero(); h = oc.z; Vector4d stoc_w = (stoc * Vector4d.UnitW()).XYZ0(); Vector4d stoc_x = (stoc * Vector4d.UnitX()).XYZ0(); Vector4d stoc_y = (stoc * Vector4d.UnitY()).XYZ0(); Vector3d2 A0 = (cameraToOcean * stoc_w).XYZ(); Vector3d2 dA = (cameraToOcean * stoc_x).XYZ(); Vector3d2 B = (cameraToOcean * stoc_y).XYZ(); Vector3d2 horizon1, horizon2; // Vector3d2 offset = new Vector3d2 (-m_offset.x, -m_offset.y, h); offset = new Vector3d2(-m_offset.x, -m_offset.y, h); // Vector3d2 offset = new Vector3d2 (0f, 0f, h); double h1 = h * (h + 2.0 * radius); double h2 = (h + radius) * (h + radius); double alpha = B.Dot(B) * h1 - B.z * B.z * h2; double beta0 = (A0.Dot(B) * h1 - B.z * A0.z * h2) / alpha; double beta1 = (dA.Dot(B) * h1 - B.z * dA.z * h2) / alpha; double gamma0 = (A0.Dot(A0) * h1 - A0.z * A0.z * h2) / alpha; double gamma1 = (A0.Dot(dA) * h1 - A0.z * dA.z * h2) / alpha; double gamma2 = (dA.Dot(dA) * h1 - dA.z * dA.z * h2) / alpha; horizon1 = new Vector3d2(-beta0, -beta1, 0.0); horizon2 = new Vector3d2(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2); Vector3d2 sunDir = new Vector3d2(m_manager.getDirectionToSun().normalized); Vector3d2 oceanSunDir = localToOcean.ToMatrix3x3d() * sunDir; oceanMaterial.SetVector("_Ocean_SunDir", oceanSunDir.ToVector3()); oceanMaterial.SetVector("_Ocean_Horizon1", horizon1.ToVector3()); oceanMaterial.SetVector("_Ocean_Horizon2", horizon2.ToVector3()); oceanMaterial.SetMatrix("_Ocean_CameraToOcean", cameraToOcean.ToMatrix4x4()); oceanMaterial.SetMatrix("_Ocean_OceanToCamera", cameraToOcean.Inverse().ToMatrix4x4()); oceanMaterial.SetMatrix("_Globals_CameraToScreen", ctos.ToMatrix4x4()); oceanMaterial.SetMatrix("_Globals_ScreenToCamera", stoc.ToMatrix4x4()); oceanMaterial.SetVector("_Ocean_CameraPos", offset.ToVector3()); oceanMaterial.SetVector("_Ocean_Color", new Color(m_oceanUpwellingColor.x, m_oceanUpwellingColor.y, m_oceanUpwellingColor.z) /* *0.1f */); oceanMaterial.SetVector("_Ocean_ScreenGridSize", new Vector2((float)m_resolution / (float)Screen.width, (float)m_resolution / (float)Screen.height)); oceanMaterial.SetFloat("_Ocean_Radius", (float)radius); // oceanMaterial.SetFloat("scale", 1); oceanMaterial.SetFloat("scale", oceanScale); oceanMaterial.SetFloat("_OceanAlpha", oceanAlpha); oceanMaterial.SetFloat("alphaRadius", alphaRadius); oceanMaterial.SetFloat("sunReflectionMultiplier", sunReflectionMultiplier); oceanMaterial.SetFloat("skyReflectionMultiplier", skyReflectionMultiplier); oceanMaterial.SetFloat("seaRefractionMultiplier", seaRefractionMultiplier); m_manager.GetSkyNode().SetOceanUniforms(oceanMaterial); }
// Use this for initialization public virtual void Start() { m_cameraToWorldMatrix = Matrix4x4d.Identity(); //using different materials for both the far and near cameras because they have different projection matrixes //the projection matrix in the shader has to match that of the camera or the projection will be wrong and the ocean will //appear to "shift around" m_oceanMaterialNear = new Material(ShaderTool.GetMatFromShader2("CompiledOceanWhiteCaps.shader")); m_oceanMaterialFar = new Material(ShaderTool.GetMatFromShader2("CompiledOceanWhiteCaps.shader")); m_manager.GetSkyNode().InitUniforms(m_oceanMaterialNear); m_manager.GetSkyNode().InitUniforms(m_oceanMaterialFar); m_oldlocalToOcean = Matrix4x4d.Identity(); m_oldworldToOcean = Matrix4x4d.Identity(); m_offset = Vector3d2.Zero(); //Create the projected grid. The resolution is the size in pixels //of each square in the grid. If the squares are small the size of //the mesh will exceed the max verts for a mesh in Unity. In this case //split the mesh up into smaller meshes. m_resolution = Mathf.Max(1, m_resolution); //The number of squares in the grid on the x and y axis int NX = Screen.width / m_resolution; int NY = Screen.height / m_resolution; numGrids = 1; // const int MAX_VERTS = 65000; //The number of meshes need to make a grid of this resolution if (NX * NY > MAX_VERTS) { numGrids += (NX * NY) / MAX_VERTS; } m_screenGrids = new Mesh[numGrids]; // waterGameObjectsNear = new GameObject[numGrids]; // waterMeshRenderersNear = new MeshRenderer[numGrids]; // waterMeshFiltersNear = new MeshFilter[numGrids]; // // waterGameObjectsFar = new GameObject[numGrids]; // waterMeshRenderersFar = new MeshRenderer[numGrids]; // waterMeshFiltersFar = new MeshFilter[numGrids]; //Make the meshes. The end product will be a grid of verts that cover //the screen on the x and y axis with the z depth at 0. This grid is then //projected as the ocean by the shader for (int i = 0; i < numGrids; i++) { NY = Screen.height / numGrids / m_resolution; m_screenGrids [i] = MakePlane(NX, NY, (float)i / (float)numGrids, 1.0f / (float)numGrids); m_screenGrids [i].bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); //bad idea, the meshes still render arbitrarily to the near and far camera and end up drawing over everything //to get around this I use drawmesh further down //seems to have better performance also // waterGameObjectsNear[i] = new GameObject(); // waterGameObjectsNear[i].transform.parent=m_manager.parentCelestialBody.transform; // waterMeshFiltersNear[i] = waterGameObjectsNear[i].AddComponent<MeshFilter>(); // waterMeshFiltersNear[i].mesh.Clear (); // waterMeshFiltersNear[i].mesh = m_screenGrids[i]; // waterGameObjectsNear[i].layer = 15; // // waterMeshRenderersNear[i] = waterGameObjectsNear[i].AddComponent<MeshRenderer>(); // // waterMeshRenderersNear[i].sharedMaterial = m_oceanMaterialNear; // waterMeshRenderersNear[i].material =m_oceanMaterialNear; // // waterMeshRenderersNear[i].castShadows = false; // waterMeshRenderersNear[i].receiveShadows = false; // // waterMeshRenderersNear[i].enabled=true; // // // waterGameObjectsFar[i] = new GameObject(); // waterGameObjectsFar[i].transform.parent=m_manager.parentCelestialBody.transform; // waterMeshFiltersFar[i] = waterGameObjectsFar[i].AddComponent<MeshFilter>(); // waterMeshFiltersFar[i].mesh.Clear (); // waterMeshFiltersFar[i].mesh = m_screenGrids[i]; // waterGameObjectsFar[i].layer = 15; // // waterMeshRenderersFar[i] = waterGameObjectsFar[i].AddComponent<MeshRenderer>(); // // waterMeshRenderersFar[i].sharedMaterial = m_oceanMaterialFar; // waterMeshRenderersFar[i].material =m_oceanMaterialFar; // // waterMeshRenderersFar[i].castShadows = false; // waterMeshRenderersFar[i].receiveShadows = false; // // waterMeshRenderersFar[i].enabled=true; } // PQS pqs = m_manager.parentCelestialBody.pqsController; // // if (pqs.ChildSpheres[0]) // UnityEngine.Object.Destroy (pqs.ChildSpheres [0]); // if (ocean) // { // UnityEngine.Object.Destroy (ocean); // } // Debug.Log("PQS.childspheres count"+pqs.ChildSpheres.Length); // PQS pqs = m_manager.parentCelestialBody.pqsController; // if (pqs.ChildSpheres [0]) { // ocean = pqs.ChildSpheres [0]; // // ocean.surfaceMaterial = new Material (ShaderTool.GetMatFromShader2 ("EmptyShader.shader")); // // ///Thanks to rbray89 for this snippet that disables the stock ocean in a clean way // GameObject container = ocean.gameObject; // // FakeOceanPQS fakeOcean1 = new GameObject ().AddComponent<FakeOceanPQS> (); // // fakeOcean1.CloneFrom (ocean); // Destroy (ocean); // // FakeOceanPQS fakeOcean = container.AddComponent<FakeOceanPQS> (); // fakeOcean.CloneFrom (fakeOcean1); // // Destroy (fakeOcean1); // // FieldInfo field = typeof(PQS).GetFields (BindingFlags.Instance | BindingFlags.NonPublic).First ( // f => f.FieldType == typeof(PQS[])); // field.SetValue (pqs, new PQS[] {fakeOcean }); // // PQSMod_CelestialBodyTransform cbt = pqs.GetComponentsInChildren<PQSMod_CelestialBodyTransform> () [0]; // cbt.secondaryFades = new PQSMod_CelestialBodyTransform.AltitudeFade[] { }; // } // fakeOceanMesh = isosphere.Create (m_manager.GetRadius()); // // // fakeOcean = new GameObject (); // fakeOceanMF = fakeOcean.AddComponent<MeshFilter>(); // fakeOceanMF.mesh = fakeOceanMesh; // fakeOcean.layer = 15; // // // fakeOcean.transform.parent = m_manager.parentCelestialBody.transform; // // fakeOceanMR = fakeOcean.AddComponent<MeshRenderer>(); // // newMat = new Material (ShaderTool.GetMatFromShader2 ("BlackShader.shader")); // fakeOceanMR.sharedMaterial = newMat; // fakeOceanMR.material =newMat; // // fakeOceanMR.castShadows = false; // fakeOceanMR.receiveShadows = false; }
public void updateStuff(Material oceanMaterial, Camera inCamera) { // m_manager.GetSkyNode ().SetOceanUniforms (m_oceanMaterial); //Calculates the required data for the projected grid // compute ltoo = localToOcean transform, where ocean frame = tangent space at // camera projection on sphere radius in local space Matrix4x4 ctol1 = inCamera.cameraToWorldMatrix; Matrix4x4d cameraToWorld = new Matrix4x4d(ctol1.m00, ctol1.m01, ctol1.m02, ctol1.m03, ctol1.m10, ctol1.m11, ctol1.m12, ctol1.m13, ctol1.m20, ctol1.m21, ctol1.m22, ctol1.m23, ctol1.m30, ctol1.m31, ctol1.m32, ctol1.m33); //Looking back, I have no idea how I figured this crap out //I probably did the math wrong anyway and it worked by sheer luck and incessant tries // Vector4 translation = m_manager.parentCelestialBody.transform.localToWorldMatrix.GetColumn (3); Vector3d translation = m_manager.parentCelestialBody.position; Matrix4x4d worldToLocal = new Matrix4x4d(1, 0, 0, -translation.x, 0, 1, 0, -translation.y, 0, 0, 1, -translation.z, 0, 0, 0, 1); Matrix4x4d camToLocal = worldToLocal * cameraToWorld; Matrix4x4d localToCam = camToLocal.Inverse(); // camera in local space relative to planet's origin Vector3d2 cl = new Vector3d2(); cl = camToLocal * Vector3d2.Zero(); double radius = m_manager.GetRadius() + m_oceanLevel; uz = cl.Normalized(); // unit z vector of ocean frame, in local space if (m_oldlocalToOcean != Matrix4x4d.Identity()) { ux = (new Vector3d2(m_oldlocalToOcean.m [1, 0], m_oldlocalToOcean.m [1, 1], m_oldlocalToOcean.m [1, 2])).Cross(uz).Normalized(); } else { ux = Vector3d2.UnitZ().Cross(uz).Normalized(); } uy = uz.Cross(ux); // unit y vector oo = uz * (radius); // origin of ocean frame, in local space //local to ocean transform //computed from oo and ux, uy, uz should be correct Matrix4x4d localToOcean = new Matrix4x4d( ux.x, ux.y, ux.z, -ux.Dot(oo), uy.x, uy.y, uy.z, -uy.Dot(oo), uz.x, uz.y, uz.z, -uz.Dot(oo), 0.0, 0.0, 0.0, 1.0); Matrix4x4d cameraToOcean = localToOcean * camToLocal; Matrix4x4d worldToOcean = localToOcean * worldToLocal; Vector3d2 delta = new Vector3d2(0, 0, 0); if (m_oldlocalToOcean != Matrix4x4d.Identity()) { delta = localToOcean * (m_oldlocalToOcean.Inverse() * Vector3d2.Zero()); m_offset += delta; } //reset offset when bigger than 20000 to avoid floating point issues when later casting the offset to float if (Mathf.Max(Mathf.Abs((float)m_offset.x), Mathf.Abs((float)m_offset.y)) > 20000f) { m_offset.x = 0.0; m_offset.y = 0.0; } m_oldlocalToOcean = localToOcean; // Matrix4x4d ctos = ModifiedProjectionMatrix (inCamera); //moved to command buffer // Matrix4x4d stoc = ctos.Inverse (); Vector3d2 oc = cameraToOcean * Vector3d2.Zero(); h = oc.z; // m_skyMaterialLocal.EnableKeyword ("ECLIPSES_ON"); // m_skyMaterialLocal.DisableKeyword ("ECLIPSES_OFF"); offset = new Vector3d2(-m_offset.x, -m_offset.y, h); //old horizon code //This breaks down when you tilt the camera by 90 degrees in any direction //I made some new horizon code down, scroll down // Vector4d stoc_w = (stoc * Vector4d.UnitW ()).XYZ0 (); // Vector4d stoc_x = (stoc * Vector4d.UnitX ()).XYZ0 (); // Vector4d stoc_y = (stoc * Vector4d.UnitY ()).XYZ0 (); // // Vector3d2 A0 = (cameraToOcean * stoc_w).XYZ (); // Vector3d2 dA = (cameraToOcean * stoc_x).XYZ (); // Vector3d2 B = (cameraToOcean * stoc_y).XYZ (); // // Vector3d2 horizon1, horizon2; // // double h1 = h * (h + 2.0 * radius); // double h2 = (h + radius) * (h + radius); // double alpha = B.Dot (B) * h1 - B.z * B.z * h2; // // double beta0 = (A0.Dot (B) * h1 - B.z * A0.z * h2) / alpha; // double beta1 = (dA.Dot (B) * h1 - B.z * dA.z * h2) / alpha; // // double gamma0 = (A0.Dot (A0) * h1 - A0.z * A0.z * h2) / alpha; // double gamma1 = (A0.Dot (dA) * h1 - A0.z * dA.z * h2) / alpha; // double gamma2 = (dA.Dot (dA) * h1 - dA.z * dA.z * h2) / alpha; // // horizon1 = new Vector3d2 (-beta0, -beta1, 0.0); // horizon2 = new Vector3d2 (beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2); Vector3d2 sunDir = new Vector3d2(m_manager.getDirectionToSun().normalized); Vector3d2 oceanSunDir = localToOcean.ToMatrix3x3d() * sunDir; oceanMaterial.SetMatrix(ShaderProperties._Globals_CameraToWorld_PROPERTY, cameraToWorld.ToMatrix4x4()); oceanMaterial.SetVector(ShaderProperties._Ocean_SunDir_PROPERTY, oceanSunDir.ToVector3()); oceanMaterial.SetMatrix(ShaderProperties._Ocean_CameraToOcean_PROPERTY, cameraToOcean.ToMatrix4x4()); oceanMaterial.SetMatrix(ShaderProperties._Ocean_OceanToCamera_PROPERTY, cameraToOcean.Inverse().ToMatrix4x4()); // oceanMaterial.SetMatrix (ShaderProperties._Globals_CameraToScreen_PROPERTY, ctos.ToMatrix4x4 ()); // oceanMaterial.SetMatrix (ShaderProperties._Globals_ScreenToCamera_PROPERTY, stoc.ToMatrix4x4 ()); oceanMaterial.SetMatrix(ShaderProperties._Globals_WorldToOcean_PROPERTY, worldToOcean.ToMatrix4x4()); oceanMaterial.SetMatrix(ShaderProperties._Globals_OceanToWorld_PROPERTY, worldToOcean.Inverse().ToMatrix4x4()); oceanMaterial.SetVector(ShaderProperties._Ocean_CameraPos_PROPERTY, offset.ToVector3()); //oceanMaterial.SetVector (ShaderProperties._Ocean_Color_PROPERTY, new Color (m_oceanUpwellingColor.x, m_oceanUpwellingColor.y, m_oceanUpwellingColor.z)); oceanMaterial.SetVector(ShaderProperties._Ocean_Color_PROPERTY, m_oceanUpwellingColor); oceanMaterial.SetVector("_Underwater_Color", m_UnderwaterColor); oceanMaterial.SetVector(ShaderProperties._Ocean_ScreenGridSize_PROPERTY, new Vector2((float)m_resolution / (float)Screen.width, (float)m_resolution / (float)Screen.height)); oceanMaterial.SetFloat(ShaderProperties._Ocean_Radius_PROPERTY, (float)(radius + m_oceanLevel)); // oceanMaterial.SetFloat("scale_PROPERTY, 1); oceanMaterial.SetFloat(ShaderProperties.scale_PROPERTY, oceanScale); oceanMaterial.SetFloat(ShaderProperties._OceanAlpha_PROPERTY, oceanAlpha); oceanMaterial.SetFloat(ShaderProperties.alphaRadius_PROPERTY, alphaRadius); oceanMaterial.SetFloat(ShaderProperties._GlobalOceanAlpha_PROPERTY, m_manager.m_skyNode.interpolatedSettings._GlobalOceanAlpha); m_manager.GetSkyNode().SetOceanUniforms(oceanMaterial); //horizon calculations //these are used to find where the horizon line is on screen //and "clamp" vertexes that are above it back to it //as the grid is projected on the whole screen, vertexes over the horizon need to be dealt with //simply passing a flag to drop fragments or moving these vertexes offscreen will cause issues //as the horizon line can be between two vertexes and the horizon line will appear "pixelated" //as whole chunks go missing //these need to be done here //1)for double precision //2)for speed Vector3d2 sphereDir = (localToCam * Vector3d2.Zero()).Normalized(); //direction to center of planet double OHL = (localToCam * Vector3d2.Zero()).Magnitude(); //distance to center of planet double rHorizon = Math.Sqrt((OHL)*(OHL)-(radius * radius)); //distance to the horizon, i.e distance to ocean sphere tangent //basic geometry yo //Theta=angle to horizon, now all that is left to do is check the viewdir against this angle in the shader double cosTheta = rHorizon / (OHL); double sinTheta = Math.Sqrt(1 - cosTheta * cosTheta); oceanMaterial.SetVector(ShaderProperties.sphereDir_PROPERTY, sphereDir.ToVector3()); oceanMaterial.SetFloat(ShaderProperties.cosTheta_PROPERTY, (float)cosTheta); oceanMaterial.SetFloat(ShaderProperties.sinTheta_PROPERTY, (float)sinTheta); if (Core.Instance.usePlanetShine) { Matrix4x4 planetShineSourcesMatrix = m_manager.m_skyNode.planetShineSourcesMatrix; Vector3d2 oceanSunDir2; for (int i = 0; i < 4; i++) { Vector4 row = planetShineSourcesMatrix.GetRow(i); oceanSunDir2 = localToOcean.ToMatrix3x3d() * new Vector3d2(row.x, row.y, row.z); planetShineSourcesMatrix.SetRow(i, new Vector4((float)oceanSunDir2.x, (float)oceanSunDir2.y, (float)oceanSunDir2.z, row.w)); } oceanMaterial.SetMatrix("planetShineSources", planetShineSourcesMatrix); oceanMaterial.SetMatrix("planetShineRGB", m_manager.m_skyNode.planetShineRGBMatrix); } m_manager.GetSkyNode().UpdatePostProcessMaterial(underwaterPostProcessingMaterial); underwaterPostProcessingMaterial.SetVector("_Underwater_Color", m_UnderwaterColor); m_oceanMaterial.SetFloat("refractionIndex", refractionIndex); m_oceanMaterial.SetFloat("transparencyDepth", transparencyDepth); m_oceanMaterial.SetFloat("darknessDepth", darknessDepth); underwaterPostProcessingMaterial.SetFloat("transparencyDepth", transparencyDepth); underwaterPostProcessingMaterial.SetFloat("darknessDepth", darknessDepth); //underwaterPostProcessingMaterial.SetFloat ("refractionIndex", refractionIndex); }
// Use this for initialization public virtual void Start() { // m_cameraToWorldMatrix = Matrix4x4d.Identity (); // //using different materials for both the far and near cameras because they have different projection matrixes //the projection matrix in the shader has to match that of the camera or the projection will be wrong and the ocean will //appear to "shift around" if (Core.Instance.oceanPixelLights) { m_oceanMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/OceanWhiteCapsPixelLights")]); } else { m_oceanMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/OceanWhiteCaps")]); } if (Core.Instance.oceanSkyReflections) { m_oceanMaterial.EnableKeyword("SKY_REFLECTIONS_ON"); m_oceanMaterial.DisableKeyword("SKY_REFLECTIONS_OFF"); } else { m_oceanMaterial.EnableKeyword("SKY_REFLECTIONS_OFF"); m_oceanMaterial.DisableKeyword("SKY_REFLECTIONS_ON"); } if (Core.Instance.usePlanetShine) { m_oceanMaterial.EnableKeyword("PLANETSHINE_ON"); m_oceanMaterial.DisableKeyword("PLANETSHINE_OFF"); } else { m_oceanMaterial.DisableKeyword("PLANETSHINE_ON"); m_oceanMaterial.EnableKeyword("PLANETSHINE_OFF"); } if (Core.Instance.oceanRefraction) { m_oceanMaterial.EnableKeyword("REFRACTION_ON"); m_oceanMaterial.DisableKeyword("REFRACTION_OFF"); } else { m_oceanMaterial.EnableKeyword("REFRACTION_OFF"); m_oceanMaterial.DisableKeyword("REFRACTION_ON"); } // m_manager.GetSkyNode ().InitUniforms (m_oceanMaterialNear); m_manager.GetSkyNode().InitUniforms(m_oceanMaterial); m_oceanMaterial.SetTexture(ShaderProperties._customDepthTexture_PROPERTY, Core.Instance.customDepthBufferTexture); m_oceanMaterial.SetTexture("_BackgroundTexture", Core.Instance.refractionTexture); m_oceanMaterial.renderQueue = 2050; m_oldlocalToOcean = Matrix4x4d.Identity(); // m_oldworldToOcean = Matrix4x4d.Identity (); m_offset = Vector3d2.Zero(); //Create the projected grid. The resolution is the size in pixels //of each square in the grid. If the squares are small the size of //the mesh will exceed the max verts for a mesh in Unity. In this case //split the mesh up into smaller meshes. m_resolution = Mathf.Max(1, m_resolution); //The number of squares in the grid on the x and y axis int NX = Screen.width / m_resolution; int NY = Screen.height / m_resolution; numGrids = 1; // const int MAX_VERTS = 65000; //The number of meshes need to make a grid of this resolution if (NX * NY > MAX_VERTS) { numGrids += (NX * NY) / MAX_VERTS; } m_screenGrids = new Mesh[numGrids]; waterGameObjects = new GameObject[numGrids]; waterMeshRenderers = new MeshRenderer[numGrids]; waterMeshFilters = new MeshFilter[numGrids]; //Make the meshes. The end product will be a grid of verts that cover //the screen on the x and y axis with the z depth at 0. This grid is then //projected as the ocean by the shader for (int i = 0; i < numGrids; i++) { NY = Screen.height / numGrids / m_resolution; m_screenGrids [i] = MakePlane(NX, NY, (float)i / (float)numGrids, 1.0f / (float)numGrids); m_screenGrids [i].bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); waterGameObjects[i] = new GameObject(); waterGameObjects[i].transform.parent = m_manager.parentCelestialBody.transform; //might be redundant waterMeshFilters[i] = waterGameObjects[i].AddComponent <MeshFilter>(); waterMeshFilters[i].mesh.Clear(); waterMeshFilters[i].mesh = m_screenGrids[i]; //waterGameObjects[i].layer = 15; waterGameObjects[i].layer = 23; waterMeshRenderers[i] = waterGameObjects[i].AddComponent <MeshRenderer>(); waterMeshRenderers[i].sharedMaterial = m_oceanMaterial; waterMeshRenderers[i].material = m_oceanMaterial; waterMeshRenderers[i].receiveShadows = false; waterMeshRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; // CommandBufferModifiedProjectionMatrix tmp = waterGameObjects[i].AddComponent<CommandBufferModifiedProjectionMatrix>(); // tmp.Core.Instance=Core.Instance; waterMeshRenderers[i].enabled = true; } cbProjectionMat = waterGameObjects[0].AddComponent <CommandBufferModifiedProjectionMatrix>(); cbProjectionMat.oceanNode = this; underwaterGameObject = new GameObject(); if (underwaterGameObject.GetComponent <MeshFilter> ()) { underwaterMeshFilter = underwaterGameObject.GetComponent <MeshFilter> (); } else { underwaterMeshFilter = underwaterGameObject.AddComponent <MeshFilter>(); } underwaterMeshFilter.mesh.Clear(); underwaterMeshFilter.mesh = MeshFactory.MakePlaneWithFrustumIndexes(); underwaterMeshFilter.mesh.bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); if (underwaterGameObject.GetComponent <MeshRenderer> ()) { underwaterMeshrenderer = underwaterGameObject.GetComponent <MeshRenderer> (); } else { underwaterMeshrenderer = underwaterGameObject.AddComponent <MeshRenderer>(); } underwaterPostProcessingMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/UnderwaterScatter")]); underwaterPostProcessingMaterial.SetOverrideTag("IgnoreProjector", "True"); m_manager.GetSkyNode().InitPostprocessMaterial(underwaterPostProcessingMaterial); underwaterPostProcessingMaterial.renderQueue = 2049; if (Core.Instance.oceanRefraction && (HighLogic.LoadedScene != GameScenes.TRACKSTATION)) { Core.Instance.refractionCam.underwaterPostProcessing = underwaterMeshrenderer; } underwaterMeshrenderer.sharedMaterial = underwaterPostProcessingMaterial; underwaterMeshrenderer.material = underwaterPostProcessingMaterial; underwaterMeshrenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; underwaterMeshrenderer.receiveShadows = false; underwaterMeshrenderer.enabled = false; //underwaterGameObject.layer = 15; underwaterGameObject.layer = 23; }
// Use this for initialization public virtual void Init() { if (Core.Instance.oceanPixelLights) { m_oceanMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/OceanWhiteCapsPixelLights")]); } else { m_oceanMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/OceanWhiteCaps")]); } if (Core.Instance.oceanSkyReflections) { m_oceanMaterial.EnableKeyword("SKY_REFLECTIONS_ON"); m_oceanMaterial.DisableKeyword("SKY_REFLECTIONS_OFF"); } else { m_oceanMaterial.EnableKeyword("SKY_REFLECTIONS_OFF"); m_oceanMaterial.DisableKeyword("SKY_REFLECTIONS_ON"); } if (Core.Instance.usePlanetShine) { m_oceanMaterial.EnableKeyword("PLANETSHINE_ON"); m_oceanMaterial.DisableKeyword("PLANETSHINE_OFF"); } else { m_oceanMaterial.DisableKeyword("PLANETSHINE_ON"); m_oceanMaterial.EnableKeyword("PLANETSHINE_OFF"); } if (Core.Instance.oceanRefraction) { m_oceanMaterial.EnableKeyword("REFRACTION_ON"); m_oceanMaterial.DisableKeyword("REFRACTION_OFF"); } else { m_oceanMaterial.EnableKeyword("REFRACTION_OFF"); m_oceanMaterial.DisableKeyword("REFRACTION_ON"); } if (Core.Instance.shadowsOnOcean && (QualitySettings.shadows != ShadowQuality.Disable)) { if (QualitySettings.shadows == ShadowQuality.HardOnly) { m_oceanMaterial.EnableKeyword("OCEAN_SHADOWS_HARD"); m_oceanMaterial.DisableKeyword("OCEAN_SHADOWS_SOFT"); } else { m_oceanMaterial.EnableKeyword("OCEAN_SHADOWS_SOFT"); m_oceanMaterial.DisableKeyword("OCEAN_SHADOWS_HARD"); } m_oceanMaterial.DisableKeyword("OCEAN_SHADOWS_OFF"); } else { m_oceanMaterial.EnableKeyword("OCEAN_SHADOWS_OFF"); m_oceanMaterial.DisableKeyword("OCEAN_SHADOWS_HARD"); m_oceanMaterial.DisableKeyword("OCEAN_SHADOWS_SOFT"); } m_oceanMaterial.SetOverrideTag("IgnoreProjector", "True"); m_manager.GetSkyNode().InitUniforms(m_oceanMaterial); m_oceanMaterial.SetTexture(ShaderProperties._customDepthTexture_PROPERTY, Core.Instance.bufferRenderingManager.depthTexture); //if (Core.Instance.oceanRefraction) m_oceanMaterial.SetTexture("_BackgroundTexture", Core.Instance.bufferRenderingManager.refractionTexture); m_oceanMaterial.renderQueue = 2501; m_oldlocalToOcean = Matrix4x4d.Identity(); m_offset = Vector3d2.Zero(); //Create the projected grid. The resolution is the size in pixels //of each square in the grid. If the squares are small the size of //the mesh will exceed the max verts for a mesh in Unity. In this case //split the mesh up into smaller meshes. m_resolution = Mathf.Max(1, m_resolution); //The number of squares in the grid on the x and y axis int NX = Screen.width / m_resolution; int NY = Screen.height / m_resolution; numGrids = 1; // const int MAX_VERTS = 65000; //The number of meshes need to make a grid of this resolution if (NX * NY > MAX_VERTS) { numGrids += (NX * NY) / MAX_VERTS; } m_screenGrids = new Mesh[numGrids]; waterGameObjects = new GameObject[numGrids]; waterMeshRenderers = new MeshRenderer[numGrids]; waterMeshFilters = new MeshFilter[numGrids]; //Make the meshes. The end product will be a grid of verts that cover //the screen on the x and y axis with the z depth at 0. This grid is then //projected as the ocean by the shader for (int i = 0; i < numGrids; i++) { NY = Screen.height / numGrids / m_resolution; m_screenGrids [i] = MakePlane(NX, NY, (float)i / (float)numGrids, 1.0f / (float)numGrids); m_screenGrids [i].bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); waterGameObjects[i] = new GameObject(); waterGameObjects[i].transform.parent = m_manager.parentCelestialBody.transform; //might be redundant waterMeshFilters[i] = waterGameObjects[i].AddComponent <MeshFilter>(); waterMeshFilters[i].mesh.Clear(); waterMeshFilters[i].mesh = m_screenGrids[i]; waterGameObjects[i].layer = 15; waterMeshRenderers[i] = waterGameObjects[i].AddComponent <MeshRenderer>(); waterMeshRenderers[i].sharedMaterial = m_oceanMaterial; waterMeshRenderers[i].material = m_oceanMaterial; waterMeshRenderers[i].receiveShadows = false; waterMeshRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; waterMeshRenderers[i].enabled = true; } oceanCameraProjectionMatModifier = waterGameObjects[0].AddComponent <OceanCameraUpdateHook>(); oceanCameraProjectionMatModifier.oceanNode = this; underwaterMaterial = new Material(ShaderReplacer.Instance.LoadedShaders[("Scatterer/UnderwaterScatterProjector")]); m_manager.GetSkyNode().InitPostprocessMaterial(underwaterMaterial); m_manager.GetSkyNode().InitPostprocessMaterial(m_oceanMaterial); underwaterMaterial.renderQueue = 2502; //draw over fairings which is 2450 and over ocean which is 2501 underwaterProjector = new AtmosphereProjector(underwaterMaterial, m_manager.parentLocalTransform, (float)m_manager.m_radius); underwaterProjector.setActivated(false); initUniforms(); //move this to separate class and make it work on every camera //refraction command buffer oceanRefractionCommandBuffer = new CommandBuffer(); oceanRefractionCommandBuffer.name = "ScattererOceanGrabScreen"; // copy screen oceanRefractionCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, Core.Instance.bufferRenderingManager.refractionTexture); Core.Instance.farCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, oceanRefractionCommandBuffer); Core.Instance.nearCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, oceanRefractionCommandBuffer); //dimming if (Core.Instance.underwaterLightDimming && (HighLogic.LoadedScene != GameScenes.MAINMENU)) { underwaterDimmingHook = (UnderwaterDimmingHook)Core.Instance.scaledSpaceCamera.gameObject.AddComponent(typeof(UnderwaterDimmingHook)); underwaterDimmingHook.oceanNode = this; } }
protected override void UpdateNode() { OceanMaterial.renderQueue = (int)RenderQueue + RenderQueueOffset; // Calculates the required data for the projected grid var c2w = (Matrix4x4d)GodManager.Instance.CameraToWorld; var cl = c2w * -Origin; // Camera in local space // TODO : Ocean origin var radius = planetoid.PlanetRadius; //Manager.IsDeformed() ? Manager.GetRadius() : 0.0f; if ((OceanType == OceanSurfaceType.Flat && cl.z > ZMin) || (radius > 0.0 && cl.Magnitude() > radius + ZMin) || (radius < 0.0 && (new Vector2d(cl.y, cl.z)).Magnitude() < -radius - ZMin)) { OldLocalToOcean = Matrix4x4d.Identity(); Offset = Vector4.zero; DrawOcean = false; return; } DrawOcean = true; Vector3d ux, uy, uz, oo; if (OceanType == OceanSurfaceType.Flat) { // Terrain ocean ux = Vector3d.UnitX(); uy = Vector3d.UnitY(); uz = Vector3d.UnitZ(); oo = new Vector3d(cl.x, cl.y, 0.0); } else { // Planet ocean uz = cl.Normalized(); // Unit z vector of ocean frame, in local space if (OldLocalToOcean != Matrix4x4d.Identity()) { ux = (new Vector3d(OldLocalToOcean.m[1, 0], OldLocalToOcean.m[1, 1], OldLocalToOcean.m[1, 2])).Cross(uz).Normalized(); } else { ux = Vector3d.UnitZ().Cross(uz).Normalized(); } uy = uz.Cross(ux); // Unit y vector oo = uz * radius; // Origin of ocean frame, in local space } // Compute l2o = LocalToOcean transform, where ocean frame = tangent space at camera projection on sphere radius in local space var l2o = new Matrix4x4d(ux.x, ux.y, ux.z, -ux.Dot(oo), uy.x, uy.y, uy.z, -uy.Dot(oo), uz.x, uz.y, uz.z, -uz.Dot(oo), 0.0, 0.0, 0.0, 1.0); // Compute c2o = CameraToOcean transform var c2o = l2o * c2w; if (OldLocalToOcean != Matrix4x4d.Identity()) { var delta = l2o * (OldLocalToOcean.Inverse() * -Origin); // TODO : Ocean origin Offset += new Vector4((float)delta.x, (float)delta.y, (float)delta.z, 0.0f); } OldLocalToOcean = l2o; var stoc = (Matrix4x4d)GodManager.Instance.ScreenToCamera; var oc = c2o * Vector3d.zero; // TODO : Ocean origin var h = oc.z; var stoc_w = (stoc * Vector4d.UnitW()).XYZ0(); var stoc_x = (stoc * Vector4d.UnitX()).XYZ0(); var stoc_y = (stoc * Vector4d.UnitY()).XYZ0(); var A0 = (c2o * stoc_w).XYZ(); var dA = (c2o * stoc_x).XYZ(); var B = (c2o * stoc_y).XYZ(); var horizon1 = Vector3d.zero; var horizon2 = Vector3d.zero; var offset = new Vector3d(-Offset.x, -Offset.y, oc.z); if (OceanType == OceanSurfaceType.Flat) { // Terrain ocean horizon1 = new Vector3d(-(h * 1e-6 + A0.z) / B.z, -dA.z / B.z, 0.0); horizon2 = Vector3d.zero; } else { // Planet ocean var h1 = h * (h + 2.0 * radius); var h2 = (h + radius) * (h + radius); var alpha = B.Dot(B) * h1 - B.z * B.z * h2; var beta0 = (A0.Dot(B) * h1 - B.z * A0.z * h2) / alpha; var beta1 = (dA.Dot(B) * h1 - B.z * dA.z * h2) / alpha; var gamma0 = (A0.Dot(A0) * h1 - A0.z * A0.z * h2) / alpha; var gamma1 = (A0.Dot(dA) * h1 - A0.z * dA.z * h2) / alpha; var gamma2 = (dA.Dot(dA) * h1 - dA.z * dA.z * h2) / alpha; horizon1 = new Vector3d(-beta0, -beta1, 0.0); horizon2 = new Vector3d(beta0 * beta0 - gamma0, 2.0 * (beta0 * beta1 - gamma1), beta1 * beta1 - gamma2); } var sunDirection = planetoid.Atmosphere.GetSunDirection(planetoid.Atmosphere.Suns[0]); var oceanSunDirection = l2o.ToMatrix3x3d() * sunDirection; OceanMaterial.SetVector("_Ocean_SunDir", oceanSunDirection.ToVector3()); OceanMaterial.SetVector("_Ocean_Horizon1", horizon1.ToVector3()); OceanMaterial.SetVector("_Ocean_Horizon2", horizon2.ToVector3()); OceanMaterial.SetMatrix("_Ocean_CameraToOcean", c2o.ToMatrix4x4()); OceanMaterial.SetMatrix("_Ocean_OceanToCamera", c2o.Inverse().ToMatrix4x4()); OceanMaterial.SetVector("_Ocean_CameraPos", offset.ToVector3()); OceanMaterial.SetVector("_Ocean_Color", UpwellingColor * 0.1f); OceanMaterial.SetVector("_Ocean_ScreenGridSize", new Vector2((float)Resolution / (float)Screen.width, (float)Resolution / (float)Screen.height)); OceanMaterial.SetFloat("_Ocean_Radius", radius); // TODO : OCEAN //Manager.GetSkyNode().SetUniforms(OceanMaterial); //Manager.GetSunNode().SetUniforms(OceanMaterial); //Manager.SetUniforms(OceanMaterial); }
// Use this for initialization public virtual void Start() { // m_cameraToWorldMatrix = Matrix4x4d.Identity (); // //using different materials for both the far and near cameras because they have different projection matrixes //the projection matrix in the shader has to match that of the camera or the projection will be wrong and the ocean will //appear to "shift around" // m_oceanMaterialNear = new Material (ShaderTool.GetMatFromShader2 ("CompiledOceanWhiteCaps.shader")); if (m_core.oceanPixelLights) { m_oceanMaterialFar = new Material(ShaderTool.GetMatFromShader2("CompiledOceanWhiteCapsPixelLights.shader")); } else { m_oceanMaterialFar = new Material(ShaderTool.GetMatFromShader2("CompiledOceanWhiteCaps.shader")); } if (m_core.oceanSkyReflections) { m_oceanMaterialFar.EnableKeyword("SKY_REFLECTIONS_ON"); m_oceanMaterialFar.DisableKeyword("SKY_REFLECTIONS_OFF"); } else { m_oceanMaterialFar.EnableKeyword("SKY_REFLECTIONS_OFF"); m_oceanMaterialFar.DisableKeyword("SKY_REFLECTIONS_ON"); } // m_manager.GetSkyNode ().InitUniforms (m_oceanMaterialNear); m_manager.GetSkyNode().InitUniforms(m_oceanMaterialFar); m_oldlocalToOcean = Matrix4x4d.Identity(); // m_oldworldToOcean = Matrix4x4d.Identity (); m_offset = Vector3d2.Zero(); //Create the projected grid. The resolution is the size in pixels //of each square in the grid. If the squares are small the size of //the mesh will exceed the max verts for a mesh in Unity. In this case //split the mesh up into smaller meshes. m_resolution = Mathf.Max(1, m_resolution); //The number of squares in the grid on the x and y axis int NX = Screen.width / m_resolution; int NY = Screen.height / m_resolution; numGrids = 1; // const int MAX_VERTS = 65000; //The number of meshes need to make a grid of this resolution if (NX * NY > MAX_VERTS) { numGrids += (NX * NY) / MAX_VERTS; } m_screenGrids = new Mesh[numGrids]; waterGameObjects = new GameObject[numGrids]; waterMeshRenderers = new MeshRenderer[numGrids]; waterMeshFilters = new MeshFilter[numGrids]; //Make the meshes. The end product will be a grid of verts that cover //the screen on the x and y axis with the z depth at 0. This grid is then //projected as the ocean by the shader for (int i = 0; i < numGrids; i++) { NY = Screen.height / numGrids / m_resolution; m_screenGrids [i] = MakePlane(NX, NY, (float)i / (float)numGrids, 1.0f / (float)numGrids); m_screenGrids [i].bounds = new Bounds(Vector3.zero, new Vector3(1e8f, 1e8f, 1e8f)); waterGameObjects[i] = new GameObject(); waterGameObjects[i].transform.parent = m_manager.parentCelestialBody.transform; //might be redundant waterMeshFilters[i] = waterGameObjects[i].AddComponent <MeshFilter>(); waterMeshFilters[i].mesh.Clear(); waterMeshFilters[i].mesh = m_screenGrids[i]; waterGameObjects[i].layer = 15; waterMeshRenderers[i] = waterGameObjects[i].AddComponent <MeshRenderer>(); waterMeshRenderers[i].sharedMaterial = m_oceanMaterialFar; waterMeshRenderers[i].material = m_oceanMaterialFar; waterMeshRenderers[i].shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; waterMeshRenderers[i].receiveShadows = false; // CommandBufferModifiedProjectionMatrix tmp = waterGameObjects[i].AddComponent<CommandBufferModifiedProjectionMatrix>(); // tmp.m_core=m_core; waterMeshRenderers[i].enabled = true; } cbProjectionMat = waterGameObjects[0].AddComponent <CommandBufferModifiedProjectionMatrix>(); cbProjectionMat.m_core = m_core; }