//	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);
        }
    }
예제 #2
0
    public void RenderShadowMap()
    {
        float far = cam.farClipPlane;

        switch (shadowMode)
        {
        case ShadowMode.None:
            cam.depthTextureMode = DepthTextureMode.None;
            break;

        case ShadowMode.Baked:
            cam.depthTextureMode = DepthTextureMode.None;
            break;

        case ShadowMode.Realtime:
            if (SystemInfo.supportsImageEffects)
            {
                cam.backgroundColor = Color.white;
                cam.clearFlags      = CameraClearFlags.SolidColor;
                cam.renderingPath   = RenderingPath.VertexLit;
                //prevent any recursive rendering
                cam.cullingMask     &= ~(WaterLayer | VLightLayer);
                cam.depthTextureMode = renderFullShadows ? DepthTextureMode.Depth : DepthTextureMode.None;

                CreateDepthTexture(lightType);

                if (RenderDepthShader != null)
                {
                    switch (lightType)
                    {
                    case LightTypes.Spot:
                    case LightTypes.Orthographic:
                        cam.targetTexture    = _depthTexture;
                        cam.projectionMatrix = CalculateProjectionMatrix();
                        if (renderFullShadows)
                        {
                            cam.Render();
                            Graphics.Blit(null, _depthTexture, PostMaterial, 6);
                        }
                        else
                        {
                            cam.RenderWithShader(RenderDepthShader, "RenderType");
                        }

                        if (shadowBlurPasses > 0)
                        {
                            //Blur the result
                            var pingPong = RenderTexture.GetTemporary(shadowMapRes, shadowMapRes, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                            pingPong.DiscardContents();
                            PostMaterial.SetFloat("_BlurSize", shadowBlurSize);
                            for (int i = 0; i < shadowBlurPasses; i++)
                            {
                                Graphics.Blit(_depthTexture, pingPong, PostMaterial, 1);
                                _depthTexture.DiscardContents();
                                Graphics.Blit(pingPong, _depthTexture, PostMaterial, 2);
                                pingPong.DiscardContents();
                            }

                            RenderTexture.ReleaseTemporary(pingPong);
                        }
                        break;

                    case LightTypes.Point:
                        cam.projectionMatrix = Matrix4x4.Perspective(90, 1.0f, 0.1f, pointLightRadius);
                        cam.SetReplacementShader(RenderDepthShader, "RenderType");
                        cam.RenderToCubemap(_depthTexture, 63);
                        cam.ResetReplacementShader();
                        break;

                    default:
                        break;
                    }
                }
                else
                {
                    Debug.LogWarning("Could not find depth shader. Cannot render shadows");
                }
            }
            break;
        }
    }
예제 #3
0
    public void RenderBakedShadowMap()
    {
        float far = cam.farClipPlane;

        if (lightType == LightTypes.Area || lightType == LightTypes.Point)
        {
            far = pointLightRadius;
        }
        else
        {
            far = spotRange;
        }

        if (SystemInfo.supportsImageEffects)
        {
            cam.backgroundColor  = Color.red;
            cam.clearFlags       = CameraClearFlags.SolidColor;
            cam.depthTextureMode = DepthTextureMode.None;
            cam.renderingPath    = RenderingPath.VertexLit;

            var bakedShadowMap = CreateBakedShadowTexture(lightType);

            if (RenderDepthShader != null)
            {
                switch (lightType)
                {
                case LightTypes.Spot:
                case LightTypes.Orthographic:
                    var tempShadowMap = RenderTexture.GetTemporary(shadowMapRes, shadowMapRes, 1, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear);
                    cam.targetTexture    = tempShadowMap;
                    cam.projectionMatrix = CalculateProjectionMatrix();
                    cam.RenderWithShader(RenderDepthShader, "RenderType");

                    //Blur the result
                    var pingPong = RenderTexture.GetTemporary(shadowMapRes, shadowMapRes, 0);
                    pingPong.DiscardContents();
                    PostMaterial.SetFloat("_BlurSize", shadowBlurSize);
                    for (int i = 0; i < shadowBlurPasses; i++)
                    {
                        Graphics.Blit(tempShadowMap, pingPong, PostMaterial, 1);
                        tempShadowMap.DiscardContents();
                        Graphics.Blit(pingPong, tempShadowMap, PostMaterial, 2);
                        pingPong.DiscardContents();
                    }

                    RenderTexture.active = tempShadowMap;

                    var tex = bakedShadowMap as Texture2D;
                    tex.ReadPixels(new Rect(0, 0, shadowMapRes, shadowMapRes), 0, 0);
                    tex.Apply();
                    spotShadow = tex;

                    RenderTexture.active = null;
                    RenderTexture.ReleaseTemporary(tempShadowMap);
                    RenderTexture.ReleaseTemporary(pingPong);

                    break;

                case LightTypes.Point:
                    cam.projectionMatrix = Matrix4x4.Perspective(90, 1.0f, 0.1f, far);
                    cam.SetReplacementShader(RenderDepthShader, "RenderType");
                    cam.RenderToCubemap(bakedShadowMap as Cubemap, 63);
                    cam.ResetReplacementShader();

                    pointShadow = bakedShadowMap;
                    break;

                default:
                    break;
                }

                AssetDatabase.CreateAsset(bakedShadowMap, "Assets/" + name + "-shadowmap-" + System.DateTime.Now.ToString("HH-MM-ss") + ".asset");

                SafeDestroy(_depthTexture);
                shadowMode = ShadowMode.Baked;
            }
            else
            {
                Debug.LogWarning("Could not find depth shader. Cannot render shadows");
            }
        }
    }