예제 #1
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);
        }
예제 #2
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);
        }