Exemplo n.º 1
0
    Vector3[] _pointsViewSpace = new Vector3[8]; // cached these values

    void CalculateMinMax(out Vector3 min, out Vector3 max, bool forceFrustrumUpdate)
    {
        if (_frustrumPoints == null || forceFrustrumUpdate)
        {
            if (lightType == LightTypes.Point || lightType == LightTypes.Area)
            {
                VLightGeometryUtil.RecalculateFrustrumPoints(cam.orthographic, pointLightRadius, spotAngle, -pointLightRadius, pointLightRadius, aspect, out _frustrumPoints);
            }
            else
            {
                VLightGeometryUtil.RecalculateFrustrumPoints(cam.orthographic, orthoSize, spotAngle, Mathf.Max(0.01f, spotNear), spotRange, aspect, out _frustrumPoints);
            }
        }

        Vector3 vecMinBounds = new Vector3(Mathf.NegativeInfinity, Mathf.NegativeInfinity, Mathf.NegativeInfinity);
        Vector3 vecMaxBounds = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);

        Matrix4x4 minMaxMatrix = _viewWorldToCameraMatrixCached * _localToWorldMatrix;

        for (int i = 0; i < _frustrumPoints.Length; i++)
        {
            _pointsViewSpace[i] = minMaxMatrix.MultiplyPoint3x4(_frustrumPoints[i]);

            vecMinBounds.x = (vecMinBounds.x > _pointsViewSpace[i].x) ? vecMinBounds.x : _pointsViewSpace[i].x;
            vecMinBounds.y = (vecMinBounds.y > _pointsViewSpace[i].y) ? vecMinBounds.y : _pointsViewSpace[i].y;
            vecMinBounds.z = (vecMinBounds.z > _pointsViewSpace[i].z) ? vecMinBounds.z : _pointsViewSpace[i].z;

            vecMaxBounds.x = (vecMaxBounds.x <= _pointsViewSpace[i].x) ? vecMaxBounds.x : _pointsViewSpace[i].x;
            vecMaxBounds.y = (vecMaxBounds.y <= _pointsViewSpace[i].y) ? vecMaxBounds.y : _pointsViewSpace[i].y;
            vecMaxBounds.z = (vecMaxBounds.z <= _pointsViewSpace[i].z) ? vecMaxBounds.z : _pointsViewSpace[i].z;
        }

        min = vecMinBounds;
        max = vecMaxBounds;
    }
Exemplo n.º 2
0
    private void CalculateMinMax(out Vector3 min, out Vector3 max, bool forceFrustrumUpdate)
    {
        if (_frustrumPoints == null || forceFrustrumUpdate)
        {
            VLightGeometryUtil.RecalculateFrustrumPoints(camera, 1.0f, out _frustrumPoints);
        }

        Vector3[] pointsViewSpace = new Vector3[8];
        Vector3   vecMinBounds    = new Vector3(Mathf.NegativeInfinity, Mathf.NegativeInfinity, Mathf.NegativeInfinity);
        Vector3   vecMaxBounds    = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
        Matrix4x4 minMaxMatrix    = _viewWorldToCameraMatrixCached * _localToWorldMatrix;

        for (int i = 0; i < _frustrumPoints.Length; i++)
        {
            pointsViewSpace[i] = minMaxMatrix.MultiplyPoint((_frustrumPoints[i]));

            vecMinBounds.x = (vecMinBounds.x > pointsViewSpace[i].x) ? vecMinBounds.x : pointsViewSpace[i].x;
            vecMinBounds.y = (vecMinBounds.y > pointsViewSpace[i].y) ? vecMinBounds.y : pointsViewSpace[i].y;
            vecMinBounds.z = (vecMinBounds.z > pointsViewSpace[i].z) ? vecMinBounds.z : pointsViewSpace[i].z;

            vecMaxBounds.x = (vecMaxBounds.x <= pointsViewSpace[i].x) ? vecMaxBounds.x : pointsViewSpace[i].x;
            vecMaxBounds.y = (vecMaxBounds.y <= pointsViewSpace[i].y) ? vecMaxBounds.y : pointsViewSpace[i].y;
            vecMaxBounds.z = (vecMaxBounds.z <= pointsViewSpace[i].z) ? vecMaxBounds.z : pointsViewSpace[i].z;
        }

        min = vecMinBounds;
        max = vecMaxBounds;
    }
Exemplo n.º 3
0
    //	[SerializeField]
    //	private AnimationCurve _planeDistribution = AnimationCurve.Linear(0, 0, 1, 1);

    void BuildMesh(bool manualPositioning, int planeCount, Vector3 minBounds, Vector3 maxBounds)
    {
        if (meshContainer == null || meshContainer.name.IndexOf(GetInstanceID().ToString(), System.StringComparison.OrdinalIgnoreCase) != 0)
        {
#if DEBUG_MODE
            Debug.Log("Creating new mesh container");
#endif
            meshContainer = new Mesh();
            meshContainer.MarkDynamic();
            meshContainer.hideFlags = HideFlags.HideAndDontSave;
            meshContainer.name      = GetInstanceID().ToString();
        }

        if (_meshFilter == null)
        {
            _meshFilter = GetComponent <MeshFilter>();
        }

        Vector3[] vertBucket      = new Vector3[VERT_COUNT];
        int[]     triBucket       = new int[TRI_COUNT];
        int       vertBucketCount = 0;
        int       triBucketCount  = 0;

        float depthOffset = 1.0f / (float)(planeCount - 1);
        float depth       = (manualPositioning) ? 1f : 0f;
        float xLeft       = 0f;
        float xRight      = 1f;
        float xBottom     = 0f;
        float xTop        = 1f;

        int vertOffset = 0;
        for (int i = 0; i < planeCount; i++)
        {
            Vector3[] verts = new Vector3[4];
            Vector3[] results;

            if (manualPositioning)
            {
                Plane[] planes = GeometryUtility.CalculateFrustumPlanes(_projectionMatrixCached * cam.worldToCameraMatrix);

                for (int j = 0; j < planes.Length; j++)
                {
                    Vector3 centre = planes[j].normal * -planes[j].distance;
                    planes[j] = new Plane(_viewWorldToCameraMatrixCached.MultiplyVector(planes[j].normal), _viewWorldToCameraMatrixCached.MultiplyPoint3x4(centre));
                }

                verts[0] = CalculateTriLerp(new Vector3(xLeft, xBottom, depth), minBounds, maxBounds);
                verts[1] = CalculateTriLerp(new Vector3(xLeft, xTop, depth), minBounds, maxBounds);
                verts[2] = CalculateTriLerp(new Vector3(xRight, xTop, depth), minBounds, maxBounds);
                verts[3] = CalculateTriLerp(new Vector3(xRight, xBottom, depth), minBounds, maxBounds);
                results  = VLightGeometryUtil.ClipPolygonAgainstPlane(verts, planes);
            }
            else
            {
                //				var dp = _planeDistribution.Evaluate(depth);
                var dp = depth;
                verts[0] = new Vector3(xLeft, xBottom, dp);
                verts[1] = new Vector3(xLeft, xTop, dp);
                verts[2] = new Vector3(xRight, xTop, dp);
                verts[3] = new Vector3(xRight, xBottom, dp);
                results  = verts;
            }

            depth += (manualPositioning) ? -depthOffset : depthOffset;

            if (results.Length > 2)
            {
                Array.Copy(results, 0, vertBucket, vertBucketCount, results.Length);
                vertBucketCount += results.Length;

                int[] tris    = new int[(results.Length - 2) * 3];
                int   vertOff = 0;
                for (int j = 0; j < tris.Length; j += 3)
                {
                    tris[j + 0] = vertOffset + 0;
                    tris[j + 1] = vertOffset + (vertOff + 1);
                    tris[j + 2] = vertOffset + (vertOff + 2);
                    vertOff++;
#if DEBUG_MODE
                    Color     lightBlue     = new Color(0, 0, 1, 0.05f);
                    Matrix4x4 cameraToWorld = _viewCameraToWorldMatrixCached;
                    Debug.DrawLine(cameraToWorld.MultiplyPoint(vertBucket[tris[j + 0]]), cameraToWorld.MultiplyPoint(vertBucket[tris[j + 1]]), lightBlue);
                    Debug.DrawLine(cameraToWorld.MultiplyPoint(vertBucket[tris[j + 1]]), cameraToWorld.MultiplyPoint(vertBucket[tris[j + 2]]), lightBlue);
                    Debug.DrawLine(cameraToWorld.MultiplyPoint(vertBucket[tris[j + 2]]), cameraToWorld.MultiplyPoint(vertBucket[tris[j + 0]]), lightBlue);
#endif
                }
                vertOffset += results.Length;
                Array.Copy(tris, 0, triBucket, triBucketCount, tris.Length);
                triBucketCount += tris.Length;
            }
        }
        meshContainer.Clear();

        Vector3[] newVerts = new Vector3[vertBucketCount];
        Array.Copy(vertBucket, newVerts, vertBucketCount);
        meshContainer.vertices = newVerts;

        int[] newTris = new int[triBucketCount];
        Array.Copy(triBucket, newTris, triBucketCount);
        meshContainer.triangles = newTris;
        meshContainer.normals   = new Vector3[vertBucketCount];
        meshContainer.uv        = new Vector2[vertBucketCount];

        Vector3 centrePT = Vector3.zero;
        foreach (var vert in _frustrumPoints)
        {
            centrePT += vert;
        }
        centrePT /= _frustrumPoints.Length;

        Bounds localBounds = new Bounds(centrePT, Vector3.zero);
        foreach (var vert in _frustrumPoints)
        {
            localBounds.Encapsulate(vert);
        }

        _meshFilter.sharedMesh        = meshContainer;
        localBounds.center           += _boundsCentreOffset;
        _meshFilter.sharedMesh.bounds = localBounds;
    }
    //	private void OnGUI()
    //	{
    //		var bounds = new Bounds();
    //		var vlights = GameObject.FindObjectsOfType<VLight>();
    //		foreach(var vlight in vlights)
    //		{
    //			bounds.max = Camera.main.cameraToWorldMatrix.MultiplyPoint(vlight.MaxBounds);
    //			bounds.min = Camera.main.cameraToWorldMatrix.MultiplyPoint(vlight.MinBounds);
    //
    //			var rect = VLightGeometryUtil.BoundsToRect(bounds, Camera.main);
    //			rect.y = rect.y;
    //			GUI.Box(rect, "");
    //		}
    //	}

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        var cam    = Camera.current;
        var planes = GeometryUtility.CalculateFrustumPlanes(cam);

        if (!Application.isPlaying)
        {
            _vlights = GameObject.FindObjectsOfType <VLight>();
        }

        if (lightsModified)
        {
            lightsModified = false;
            _vlights       = GameObject.FindObjectsOfType <VLight>();
        }

        var bounds            = new Bounds();
        var lightsVisible     = false;
        var renderInterleaved = false;

        for (var i = 0; i < _vlights.Length; i++)
        {
            var vlight = _vlights[i];
            if (GeometryUtility.TestPlanesAABB(planes, vlight.MeshRender.bounds))
            {
                bounds.max = cam.cameraToWorldMatrix.MultiplyPoint(vlight.MaxBounds);
                bounds.min = cam.cameraToWorldMatrix.MultiplyPoint(vlight.MinBounds);
                var rect = VLightGeometryUtil.BoundsToRect(bounds, cam);
                var area = rect.width * rect.height;
                if (area > (minInterleavedRes * minInterleavedRes))
                {
                    renderInterleaved = true;
                }
                lightsVisible = true;
            }
        }

        if (!lightsVisible)
        {
            Graphics.Blit(source, destination);
            return;
        }

        var downsampleFactor = Mathf.Clamp(downSample, 1, 20);

        blurIterations = Mathf.Clamp(blurIterations, 0, 20);

        if (_useBilateralFiltering)
        {
            downsampleFactor = 2;
        }

        var width             = cam.pixelWidth;
        var height            = cam.pixelHeight;
        var dsWidth           = cam.pixelWidth / downsampleFactor;
        var dsHeight          = cam.pixelHeight / downsampleFactor;
        var frameBufferFormat = _useHighPrecisionFrameBuffer ? RenderTextureFormat.ARGBFloat : RenderTextureFormat.ARGB32;

#if UNITY_EDITOR
        if (!SystemInfo.SupportsRenderTextureFormat(frameBufferFormat))
        {
            frameBufferFormat = RenderTextureFormat.ARGBHalf;
            if (!SystemInfo.SupportsRenderTextureFormat(frameBufferFormat))
            {
                frameBufferFormat = RenderTextureFormat.ARGB32;
                Debug.LogWarning("Platform does not support floating point textures");
            }
        }
#endif

        // 4 samples for the interleaved buffer
        var bufferA = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, frameBufferFormat);

        if (interleavedBuffer != null && (interleavedBuffer.width != width || interleavedBuffer.height != height))
        {
            if (Application.isPlaying)
            {
                Destroy(interleavedBuffer);
            }
            else
            {
                DestroyImmediate(interleavedBuffer);
            }
            interleavedBuffer = null;
        }

        if (interleavedBuffer == null)
        {
            interleavedBuffer = new RenderTexture(width, height, 0);

            interleavedBuffer.hideFlags = HideFlags.HideAndDontSave;
        }

        var ppCamera = GetPPCamera();
        ppCamera.CopyFrom(cam);
        ppCamera.enabled             = false;
        ppCamera.depthTextureMode    = DepthTextureMode.None;
        ppCamera.clearFlags          = CameraClearFlags.SolidColor;
        ppCamera.cullingMask         = _volumeLightLayer;
        ppCamera.useOcclusionCulling = false;
        ppCamera.backgroundColor     = Color.clear;
        ppCamera.renderingPath       = RenderingPath.VertexLit;

        renderingInterleaved = false;

        if (useInterleavedSampling && renderInterleaved)
        {
            var bufferB = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, frameBufferFormat);
            var bufferC = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, frameBufferFormat);
            var bufferD = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, frameBufferFormat);

            // For odd projection matrices
            ppCamera.projectionMatrix = cam.projectionMatrix;
            ppCamera.pixelRect        = new Rect(
                0,
                0,
                cam.pixelWidth / cam.rect.width + Screen.width / cam.rect.width,
                cam.pixelHeight / cam.rect.height + Screen.height / cam.rect.height);

            // Render the interleaved samples
            float offset = 0.0f;

            renderCount = 0;
            RenderSample(offset, ppCamera, bufferA);
            if (renderCount == 0)
            {
                Graphics.Blit(source, destination);
                RenderTexture.ReleaseTemporary(bufferA);
                RenderTexture.ReleaseTemporary(bufferB);
                RenderTexture.ReleaseTemporary(bufferC);
                RenderTexture.ReleaseTemporary(bufferD);
                return;
            }

            renderingInterleaved = true;

            offset += ditherOffset;
            RenderSample(offset, ppCamera, bufferB);
            offset += ditherOffset;
            RenderSample(offset, ppCamera, bufferC);
            offset += ditherOffset;
            RenderSample(offset, ppCamera, bufferD);

            //Combine the 4 samples to make an interleaved image and the edge border
            PostMaterial.SetTexture("_MainTexA", bufferA);
            PostMaterial.SetTexture("_MainTexB", bufferB);
            PostMaterial.SetTexture("_MainTexC", bufferC);
            PostMaterial.SetTexture("_MainTexD", bufferD);
            interleavedBuffer.DiscardContents();
            Graphics.Blit(null, interleavedBuffer, PostMaterial, 0);

            RenderTexture.ReleaseTemporary(bufferB);
            RenderTexture.ReleaseTemporary(bufferC);
            RenderTexture.ReleaseTemporary(bufferD);
        }
        else
        {
            ppCamera.projectionMatrix = cam.projectionMatrix;
            ppCamera.pixelRect        = new Rect(
                0,
                0,
                cam.pixelWidth / cam.rect.width + Screen.width / cam.rect.width,
                cam.pixelHeight / cam.rect.height + Screen.height / cam.rect.height);

            renderCount = 0;
            RenderSample(0, ppCamera, bufferA);
            if (renderCount == 0)
            {
                Graphics.Blit(source, destination);
                RenderTexture.ReleaseTemporary(bufferA);
                return;
            }

            Graphics.Blit(bufferA, interleavedBuffer);
        }

        renderingInterleaved = false;


        var pingPong = RenderTexture.GetTemporary(width, height, 0);
        pingPong.DiscardContents();

        PostMaterial.SetFloat("_BlurSize", blurRadius);

        if (_useBilateralFiltering)
        {
            var quarterDepthTexture = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear, 1);
            //quarterDepthTexture.filterMode = FilterMode.Point;
            quarterDepthTexture.wrapMode = TextureWrapMode.Clamp;
            Graphics.Blit(source, quarterDepthTexture, DownscaleDepthMaterial);

            PostMaterial.SetFloat("BlurDepthFalloff", _blurDepth);
            PostMaterial.SetTexture("LowResDepthTexture", quarterDepthTexture);

            for (int i = 0; i < blurIterations; i++)
            {
                PostMaterial.SetVector("BlurDir", new Vector2(0, blurRadius));
                Graphics.Blit(interleavedBuffer, pingPong, PostMaterial, 4);

                PostMaterial.SetVector("BlurDir", new Vector2(blurRadius, 0));
                Graphics.Blit(pingPong, interleavedBuffer, PostMaterial, 4);

                PostMaterial.SetVector("BlurDir", new Vector2(0, blurRadius));
                Graphics.Blit(interleavedBuffer, pingPong, PostMaterial, 4);

                PostMaterial.SetVector("BlurDir", new Vector2(blurRadius, 0));
                Graphics.Blit(pingPong, interleavedBuffer, PostMaterial, 4);
            }

            RenderTexture.ReleaseTemporary(pingPong);
            RenderTexture.ReleaseTemporary(bufferA);

            PostMaterial.SetFloat("DepthThreshold", _depthThreshold);

            var interleavedBufferPoint = RenderTexture.GetTemporary(dsWidth, dsHeight, 0, RenderTextureFormat.ARGB32);
            Graphics.Blit(interleavedBuffer, interleavedBufferPoint);
            interleavedBufferPoint.filterMode = FilterMode.Point;

            PostMaterial.SetTexture("_MainTexBlurred", interleavedBuffer);
            PostMaterial.SetTexture("_MainTexBlurredPoint", interleavedBufferPoint);

            Graphics.Blit(source, destination, PostMaterial, 3);

            RenderTexture.ReleaseTemporary(interleavedBufferPoint);
            RenderTexture.ReleaseTemporary(quarterDepthTexture);
        }
        else
        {
            for (int i = 0; i < blurIterations; i++)
            {
                Graphics.Blit(interleavedBuffer, pingPong, PostMaterial, 1);
                interleavedBuffer.DiscardContents();
                Graphics.Blit(pingPong, interleavedBuffer, PostMaterial, 2);
                pingPong.DiscardContents();
            }

            PostMaterial.SetTexture("_MainTexBlurred", interleavedBuffer);
            Graphics.Blit(source, destination, PostMaterial, 5);

            RenderTexture.ReleaseTemporary(pingPong);
            RenderTexture.ReleaseTemporary(bufferA);
        }
    }