Beispiel #1
0
        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);
        }
Beispiel #2
0
        // 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();
        }
Beispiel #3
0
        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));
            }
        }
Beispiel #4
0
        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));
        }
Beispiel #6
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);
            }
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        // 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;
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        // 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;
        }
Beispiel #11
0
        // 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;
            }
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        // 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;
        }