// 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); } }
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; } }
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"); } } }