/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); int pass = 4; _material.SetVector(_LightDir, new Vector4(_light.transform.forward.x, _light.transform.forward.y, _light.transform.forward.z, 1.0f / (_light.range * _light.range))); _material.SetVector(_LightColor, _light.color * _light.intensity * intensity * (1f / SampleCount)); // setup frustum corners for world position reconstruction // bottom left _frustumCorners[0] = Camera.current.ViewportToWorldPoint(new Vector3(0, 0, Camera.current.farClipPlane)); // top left _frustumCorners[2] = Camera.current.ViewportToWorldPoint(new Vector3(0, 1, Camera.current.farClipPlane)); // top right _frustumCorners[3] = Camera.current.ViewportToWorldPoint(new Vector3(1, 1, Camera.current.farClipPlane)); // bottom right _frustumCorners[1] = Camera.current.ViewportToWorldPoint(new Vector3(1, 0, Camera.current.farClipPlane)); _material.SetVectorArray(_FrustumCorners, _frustumCorners); if (_light.shadows != LightShadows.None) { _commandBuffer.SetGlobalFloat(_DirectionalLightFlag, 1); _commandBuffer.EnableShaderKeyword("SHADOWS_DEPTH_ON"); _commandBuffer.Blit(null, renderer.volumeLightTexture, _material, pass); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { // light was destroyed without deregistring, deregister now if (_light == null || _light.gameObject == null) { VolumetricLightRenderer.PreRenderEvent -= VolumetricLightRenderer_PreRenderEvent; return; } if (!_light.gameObject.activeInHierarchy || _light.enabled == false) { return; } _material.SetVector("_CameraForward", Camera.current.transform.forward); _material.SetInt("_SampleCount", SampleCount); _material.SetVector("_NoiseVelocity", new Vector4(NoiseVelocity.x, NoiseVelocity.y) * NoiseScale); _material.SetVector("_NoiseData", new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); _material.SetVector("_MieG", new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector("_VolumetricLight", new Vector4(ScatteringCoef, ExtinctionCoef, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture("_CameraDepthTexture", renderer.GetVolumeLightDepthBuffer()); //if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { //_material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.LessEqual); //_material.DisableKeyword("MANUAL_ZTEST"); } //else { _material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Always); // downsampled light buffer can't use native zbuffer for ztest, try to perform ztest in pixel shader to avoid ray marching for occulded geometry //_material.EnableKeyword("MANUAL_ZTEST"); } if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector("_HeightFog", new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } if (_light.type == LightType.Point) { SetupPointLight(renderer, viewProj); } else if (_light.type == LightType.Spot) { SetupSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { SetupDirectionalLight(renderer, viewProj); } }
private void InitSpotLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 1; if (!IsCameraInSpotLightBounds()) { pass = 3; } _material.SetFloat(_CosAngle, Mathf.Cos((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad)); _material.EnableKeyword("SPOT"); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } if (_light.cookie == null) { _material.SetTexture(_LightTexture0, VolumetricLightRenderer.GetDefaultSpotCookie()); } else { _material.SetTexture(_LightTexture0, _light.cookie); } }
private void InitdirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 4; _material.SetPass(pass); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } _material.SetFloat(_MaxRayLength, MaxRayLength); if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture(_LightTexture0, _light.cookie); } }
private void InitPointLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 0; if (!IsCameraInPointLightBounds()) { pass = 2; } _material.SetPass(pass); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } if (_light.cookie == null) { _material.EnableKeyword("POINT"); _material.DisableKeyword("POINT_COOKIE"); } else { _material.EnableKeyword("POINT_COOKIE"); _material.DisableKeyword("POINT"); _material.SetTexture(_LightTexture0, _light.cookie); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { // light was destroyed without deregistring, deregister now if (_light == null) { VolumetricLightRenderer.PreRenderEvent -= VolumetricLightRenderer_PreRenderEvent; return; } if (_light.enabled == false) { return; } _material.SetVector(_CameraForward, Camera.current.transform.forward); // downsampled light buffer can't use native zbuffer for ztest, try to perform ztest in pixel shader to avoid ray marching for occulded geometry //_material.EnableKeyword("MANUAL_ZTEST"); if (_light.type == LightType.Point) { SetupPointLight(renderer, viewProj); } else if (_light.type == LightType.Spot) { SetupSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { SetupDirectionalLight(renderer, viewProj); } }
/// <summary> /// Inits the set. /// </summary> private void initSet(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _material.SetInt(_SampleCount, SampleCount); _material.SetVector(_NoiseVelocity, new Vector4(NoiseVelocity.x, NoiseVelocity.y) * NoiseScale); _material.SetVector(_NoiseData, new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); _material.SetVector(_MieG, new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector(_VolumetricLight, new Vector4(0, 0, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture(_CameraDepthTexture, renderer.volumeDepthTexture); _material.SetFloat(_ZTest, (int)UnityEngine.Rendering.CompareFunction.Always); if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector(_HeightFog, new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } if (_light.type == LightType.Point) { InitPointLight(renderer, viewProj); } else if (_light.type == LightType.Spot) { InitSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { InitdirectionalLight(renderer, viewProj); } VolumetricLightRenderer.PreRenderEvent -= initSet; }
public void OnPreRender() { Matrix4x4 matrix4x = Matrix4x4.Perspective(this._camera.fieldOfView, this._camera.aspect, 0.01f, this._camera.farClipPlane); matrix4x = GL.GetGPUProjectionMatrix(matrix4x, true); this._viewProj = matrix4x * this._camera.worldToCameraMatrix; this._preLightPass.Clear(); bool flag = SystemInfo.graphicsShaderLevel > 40; if (this.Resolution == VolumetricLightRenderer.VolumtericResolution.Quarter) { Texture source = null; this._preLightPass.Blit(source, this._halfDepthBuffer, this._bilateralBlurMaterial, (!flag) ? 10 : 4); this._preLightPass.Blit(source, this._quarterDepthBuffer, this._bilateralBlurMaterial, (!flag) ? 11 : 6); this._preLightPass.SetRenderTarget(this._quarterVolumeLightTexture); } else if (this.Resolution == VolumetricLightRenderer.VolumtericResolution.Half) { Texture source2 = null; this._preLightPass.Blit(source2, this._halfDepthBuffer, this._bilateralBlurMaterial, (!flag) ? 10 : 4); this._preLightPass.SetRenderTarget(this._halfVolumeLightTexture); } else { this._preLightPass.SetRenderTarget(this._volumeLightTexture); } this._preLightPass.ClearRenderTarget(false, true, new Color(0f, 0f, 0f, 1f)); this.UpdateMaterialParameters(); if (VolumetricLightRenderer.PreRenderEvent != null) { VolumetricLightRenderer.PreRenderEvent(this, this._viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupPointLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); int pass = 0; if (!IsCameraInPointLightBounds()) { pass = 2; } Mesh mesh = VolumetricLightRenderer.GetPointLightMesh(); float scale = _light.range * 2.0f; Matrix4x4 world = Matrix4x4.TRS(transform.position, _light.transform.rotation, new Vector3(scale, scale, scale)); _material.SetMatrix(_WorldViewProj, viewProj * world); _material.SetMatrix(_WorldView, Camera.current.worldToCameraMatrix * world); _material.SetVector(_LightPos, new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetColor(_LightColor, _light.color * _light.intensity * intensity * (1f / SampleCount)); if (_light.cookie != null) { Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; _material.SetMatrix(_MyLightMatrix0, view); } bool forceShadowsOff = false; if ((_light.transform.position - Camera.current.transform.position).magnitude >= QualitySettings.shadowDistance) { forceShadowsOff = true; } if (_light.shadows != LightShadows.None && forceShadowsOff == false) { _material.EnableKeyword("SHADOWS_CUBE"); _commandBuffer.SetGlobalTexture(_ShadowMapTexture, BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.volumeLightTexture); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_CUBE"); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { this._commandBuffer.Clear(); int num = 4; this._material.SetPass(num); if (this.Noise) { this._material.EnableKeyword("NOISE"); } else { this._material.DisableKeyword("NOISE"); } this._material.SetVector("_LightDir", new Vector4((float)((Component)this._light).get_transform().get_forward().x, (float)((Component)this._light).get_transform().get_forward().y, (float)((Component)this._light).get_transform().get_forward().z, (float)(1.0 / ((double)this._light.get_range() * (double)this._light.get_range())))); this._material.SetVector("_LightColor", Color.op_Implicit(Color.op_Multiply(this._light.get_color(), this._light.get_intensity()))); this._material.SetFloat("_MaxRayLength", this.MaxRayLength); if (Object.op_Equality((Object)this._light.get_cookie(), (Object)null)) { this._material.EnableKeyword("DIRECTIONAL"); this._material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { this._material.EnableKeyword("DIRECTIONAL_COOKIE"); this._material.DisableKeyword("DIRECTIONAL"); this._material.SetTexture("_LightTexture0", this._light.get_cookie()); } this._frustumCorners[0] = Vector4.op_Implicit(Camera.get_current().ViewportToWorldPoint(new Vector3(0.0f, 0.0f, Camera.get_current().get_farClipPlane()))); this._frustumCorners[2] = Vector4.op_Implicit(Camera.get_current().ViewportToWorldPoint(new Vector3(0.0f, 1f, Camera.get_current().get_farClipPlane()))); this._frustumCorners[3] = Vector4.op_Implicit(Camera.get_current().ViewportToWorldPoint(new Vector3(1f, 1f, Camera.get_current().get_farClipPlane()))); this._frustumCorners[1] = Vector4.op_Implicit(Camera.get_current().ViewportToWorldPoint(new Vector3(1f, 0.0f, Camera.get_current().get_farClipPlane()))); this._material.SetVectorArray("_FrustumCorners", this._frustumCorners); Texture texture = (Texture)null; if (this._light.get_shadows() != null) { this._material.EnableKeyword("SHADOWS_DEPTH"); this._commandBuffer.Blit(texture, RenderTargetIdentifier.op_Implicit((Texture)renderer.GetVolumeLightBuffer()), this._material, num); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, this._commandBuffer, viewProj); } else { this._material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.Blit(texture, RenderTargetIdentifier.op_Implicit((Texture)renderer.GetVolumeLightBuffer()), this._material, num); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 4; this._material.SetPass(pass); if (this.Noise) { this._material.EnableKeyword("NOISE"); } else { this._material.DisableKeyword("NOISE"); } this._material.SetVector("_LightDir", new Vector4(this._light.transform.forward.x, this._light.transform.forward.y, this._light.transform.forward.z, 1f / (this._light.range * this._light.range))); this._material.SetVector("_LightColor", this._light.color * this._light.intensity); this._material.SetFloat("_MaxRayLength", this.MaxRayLength); if (this._light.cookie == null) { this._material.EnableKeyword("DIRECTIONAL"); this._material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { this._material.EnableKeyword("DIRECTIONAL_COOKIE"); this._material.DisableKeyword("DIRECTIONAL"); this._material.SetTexture("_LightTexture0", this._light.cookie); } this._frustumCorners[0] = Camera.current.ViewportToWorldPoint(new Vector3(0f, 0f, Camera.current.farClipPlane)); this._frustumCorners[2] = Camera.current.ViewportToWorldPoint(new Vector3(0f, 1f, Camera.current.farClipPlane)); this._frustumCorners[3] = Camera.current.ViewportToWorldPoint(new Vector3(1f, 1f, Camera.current.farClipPlane)); this._frustumCorners[1] = Camera.current.ViewportToWorldPoint(new Vector3(1f, 0f, Camera.current.farClipPlane)); this._material.SetVectorArray("_FrustumCorners", this._frustumCorners); Texture source = null; if (this._light.shadows != LightShadows.None) { this._material.EnableKeyword("SHADOWS_DEPTH"); this._commandBuffer.Blit(source, renderer.GetVolumeLightBuffer(), this._material, pass); if (this.CustomRenderEvent != null) { this.CustomRenderEvent(renderer, this, this._commandBuffer, viewProj); } } else { this._material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.Blit(source, renderer.GetVolumeLightBuffer(), this._material, pass); if (this.CustomRenderEvent != null) { this.CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
private void OnImageEvent(VolumetricLightRenderer renderer) { if (Shader.GetGlobalFloat(_DirectionalLightFlag) < 0.5f) { Graphics.Blit(null, renderer.volumeLightTexture, _material, 4); } else { Shader.SetGlobalFloat(_DirectionalLightFlag, 0); Shader.DisableKeyword("SHADOWS_DEPTH_ON"); } }
public void ApplyUpdates() { if (_volumeRenderer == null) { _volumeRenderer = Camera.main.GetComponent <VolumetricLightRenderer>(); } if (_volumeRenderer != null) { _volumeRenderer.enabled = enabled; } }
static void Postfix(VolumetricLightRenderer __instance) { VolumetricLightRenderer VolumetricPatcherPt2 = __instance as VolumetricLightRenderer; if (PatchConfigs.I_Have_A_Strong_PC_And_GPU == true) { VolumetricPatcherPt2.Resolution = VolumetricLightRenderer.VolumtericResolution.Half; } else { VolumetricPatcherPt2.Resolution = VolumetricLightRenderer.VolumtericResolution.Quarter; } }
private void InitdirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture(_LightTexture0, _light.cookie); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); int pass = 4; _material.SetVector(_LightDir, new Vector4(_light.transform.forward.x, _light.transform.forward.y, _light.transform.forward.z, 1.0f / (_light.range * _light.range))); _material.SetVector(_LightColor, _light.color * _light.intensity * intensity); // setup frustum corners for world position reconstruction // bottom left _frustumCorners[0] = Camera.current.ViewportToWorldPoint(new Vector3(0, 0, Camera.current.farClipPlane)); // top left _frustumCorners[2] = Camera.current.ViewportToWorldPoint(new Vector3(0, 1, Camera.current.farClipPlane)); // top right _frustumCorners[3] = Camera.current.ViewportToWorldPoint(new Vector3(1, 1, Camera.current.farClipPlane)); // bottom right _frustumCorners[1] = Camera.current.ViewportToWorldPoint(new Vector3(1, 0, Camera.current.farClipPlane)); _material.SetVectorArray(_FrustumCorners, _frustumCorners); Texture nullTexture = null; if (_light.shadows != LightShadows.None) { _material.EnableKeyword("SHADOWS_DEPTH"); _commandBuffer.Blit(nullTexture, renderer.volumeLightTexture, _material, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.Blit(nullTexture, renderer.volumeLightTexture, _material, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); Vector3 forwd = _light.transform.forward; _material.SetVector(_LightDir, new Vector4(forwd.x, forwd.y, forwd.z, 1.0f / (_light.range * _light.range))); _material.SetVector(_LightFinalColor, _light.color * _light.intensity * intensity * (1f / SampleCount)); if (_light.shadows != LightShadows.None) { _commandBuffer.SetGlobalFloat(_DirectionalLightFlag, 1); _commandBuffer.EnableShaderKeyword("SHADOWS_DEPTH_ON"); _commandBuffer.Blit(null, renderer.volumeLightTexture, _material, 0); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { if (!_light.gameObject.activeInHierarchy) { return; } _material.SetInt("_SampleCount", SampleCount); _material.SetVector("_NoiseVelocity", new Vector4(NoiseVelocity.x, NoiseVelocity.y)); _material.SetVector("_NoiseData", new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { _material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.LessEqual); //_material.DisableKeyword("MANUAL_ZTEST"); } else { _material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Always); // downsampled light buffer can't use native zbuffer for ztest, try to perform ztest in pixel shader to avoid ray marching for occulded geometry //_material.EnableKeyword("MANUAL_ZTEST"); } if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector("_HeightFog", new Vector4(MinHeight, MaxHeight - MinHeight, MaxHeightIntensity, MinHeightIntensity - MaxHeightIntensity)); } else { _material.DisableKeyword("HEIGHT_FOG"); } if (_light.type == LightType.Point) { SetupPointLight(renderer, viewProj); } else if (_light.type == LightType.Spot) { SetupSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { SetupDirectionalLight(renderer, viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { // light was destroyed without deregistring, deregister now if (_light == null || _light.gameObject == null) { VolumetricLightRenderer.PreRenderEvent -= VolumetricLightRenderer_PreRenderEvent; } if (!_light.gameObject.activeInHierarchy || _light.enabled == false) { return; } _material.SetVector("_CameraForward", Camera.current.transform.forward); _material.SetInt("_SampleCount", SampleCount); _material.SetVector("_NoiseVelocity", new Vector4(NoiseVelocity.x, NoiseVelocity.y) * NoiseScale); _material.SetVector("_NoiseData", new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); _material.SetVector("_MieG", new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector("_VolumetricLight", new Vector4(ScatteringCoef, ExtinctionCoef, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture("_CameraDepthTexture", renderer.GetVolumeLightDepthBuffer()); if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector("_HeightFog", new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } if (_light.type == LightType.Point) { SetupPointLight(renderer, viewProj); } else if (_light.type == LightType.Spot) { SetupSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { SetupDirectionalLight(renderer, viewProj); } }
private void VolumetricLightRenderer_PreRenderEvent( VolumetricLightRenderer renderer, Matrix4x4 viewProj) { if (Object.op_Equality((Object)this._light, (Object)null) || Object.op_Equality((Object)((Component)this._light).get_gameObject(), (Object)null)) { VolumetricLightRenderer.PreRenderEvent -= new Action <VolumetricLightRenderer, Matrix4x4>(this.VolumetricLightRenderer_PreRenderEvent); } if (!((Component)this._light).get_gameObject().get_activeInHierarchy() || !((Behaviour)this._light).get_enabled()) { return; } this._material.SetVector("_CameraForward", Vector4.op_Implicit(((Component)Camera.get_current()).get_transform().get_forward())); this._material.SetInt("_SampleCount", this.SampleCount); this._material.SetVector("_NoiseVelocity", Vector4.op_Multiply(new Vector4((float)this.NoiseVelocity.x, (float)this.NoiseVelocity.y), this.NoiseScale)); this._material.SetVector("_NoiseData", new Vector4(this.NoiseScale, this.NoiseIntensity, this.NoiseIntensityOffset)); this._material.SetVector("_MieG", new Vector4((float)(1.0 - (double)this.MieG * (double)this.MieG), (float)(1.0 + (double)this.MieG * (double)this.MieG), 2f * this.MieG, 0.07957747f)); this._material.SetVector("_VolumetricLight", new Vector4(this.ScatteringCoef, this.ExtinctionCoef, this._light.get_range(), 1f - this.SkyboxExtinctionCoef)); this._material.SetTexture("_CameraDepthTexture", (Texture)renderer.GetVolumeLightDepthBuffer()); this._material.SetFloat("_ZTest", 8f); if (this.HeightFog) { this._material.EnableKeyword("HEIGHT_FOG"); this._material.SetVector("_HeightFog", new Vector4(this.GroundLevel, this.HeightScale)); } else { this._material.DisableKeyword("HEIGHT_FOG"); } if (this._light.get_type() == 2) { this.SetupPointLight(renderer, viewProj); } else if (this._light.get_type() == null) { this.SetupSpotLight(renderer, viewProj); } else { if (this._light.get_type() != 1) { return; } this.SetupDirectionalLight(renderer, viewProj); } }
/// <summary> /// Inits the set. /// </summary> private void initSet(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _material.SetInt(_SampleCount, SampleCount); _material.SetVector(_MieG, new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector(_VolumetricLight, new Vector4(0, 0, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture(_CameraDepthTexture, renderer.volumeDepthTexture); _material.SetFloat(_ZTest, (int)UnityEngine.Rendering.CompareFunction.Always); if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector(_HeightFog, new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } InitdirectionalLight(renderer, viewProj); VolumetricLightRenderer.PreRenderEvent -= initSet; }
private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { if (!this._light.gameObject.activeInHierarchy || !this._light.enabled) { return; } this._material.SetVector("_CameraForward", Camera.current.transform.forward); this._material.SetInt("_SampleCount", this.SampleCount); this._material.SetVector("_NoiseVelocity", new Vector4(this.NoiseVelocity.x, this.NoiseVelocity.y) * this.NoiseScale); this._material.SetVector("_NoiseData", new Vector4(this.NoiseScale, this.NoiseIntensity, this.NoiseIntensityOffset)); this._material.SetVector("_MieG", new Vector4(1f - this.MieG * this.MieG, 1f + this.MieG * this.MieG, 2f * this.MieG, 0.07957747f)); this._material.SetVector("_VolumetricLight", new Vector4(this.ScatteringCoef, this.ExtinctionCoef, this._light.range, 1f - this.SkyboxExtinctionCoef)); this._material.SetTexture("_CameraDepthTexture", renderer.GetVolumeLightDepthBuffer()); this._material.SetFloat("_ZTest", 8f); if (this.HeightFog) { this._material.EnableKeyword("HEIGHT_FOG"); this._material.SetVector("_HeightFog", new Vector4(this.GroundLevel, this.HeightScale)); } else { this._material.DisableKeyword("HEIGHT_FOG"); } if (this._light.type == LightType.Point) { this.SetupPointLight(renderer, viewProj); } else if (this._light.type == LightType.Spot) { this.SetupSpotLight(renderer, viewProj); } else if (this._light.type == LightType.Directional) { this.SetupDirectionalLight(renderer, viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupSpotLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 1; if (!IsCameraInSpotLightBounds()) { pass = 3; } Mesh mesh = VolumetricLightRenderer.GetSpotLightMesh(); float scale = _light.range; float angleScale = Mathf.Tan((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad) * _light.range; Matrix4x4 world = Matrix4x4.TRS(transform.position, transform.rotation, new Vector3(angleScale, angleScale, scale)); Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; Matrix4x4 clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.0f), Quaternion.identity, new Vector3(-0.5f, -0.5f, 1.0f)); Matrix4x4 proj = Matrix4x4.Perspective(_light.spotAngle, 1, 0, 1); _material.SetMatrix("_MyLightMatrix0", clip * proj * view); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); Vector3 apex = transform.position; Vector3 axis = transform.forward; // plane equation ax + by + cz + d = 0; precompute d here to lighten the shader Vector3 center = apex + axis * _light.range; float d = -Vector3.Dot(center, axis); // update material _material.SetFloat("_PlaneD", d); _material.SetFloat("_CosAngle", Mathf.Cos((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad)); _material.SetVector("_ConeApex", new Vector4(apex.x, apex.y, apex.z)); _material.SetVector("_ConeAxis", new Vector4(axis.x, axis.y, axis.z)); _material.EnableKeyword("SPOT"); if (Noise) _material.EnableKeyword("NOISE"); else _material.DisableKeyword("NOISE"); if (_light.cookie == null) { _material.SetTexture("_LightTexture0", VolumetricLightRenderer.GetDefaultSpotCookie()); } else { _material.SetTexture("_LightTexture0", _light.cookie); } bool forceShadowsOff = false; if ((_light.transform.position - Camera.current.transform.position).magnitude >= QualitySettings.shadowDistance) forceShadowsOff = true; if (_light.shadows != LightShadows.None && forceShadowsOff == false) { clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f)); proj = Matrix4x4.Perspective(_light.spotAngle, 1, _light.shadowNearPlane, _light.range); Matrix4x4 m = clip * proj; m[0, 2] *= -1; m[1, 2] *= -1; m[2, 2] *= -1; m[3, 2] *= -1; //view = _light.transform.worldToLocalMatrix; _material.SetMatrix("_MyWorld2Shadow", m * view); _material.SetMatrix("_WorldView", m * view); _material.EnableKeyword("SHADOWS_DEPTH"); _commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } else { _material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 VP) { if (_light == null || _light.gameObject == null) { VolumetricLightRenderer.PreRenderEvent -= VolumetricLightRenderer_PreRenderEvent; } if (!_light.gameObject.activeInHierarchy || _light.enabled == false) { return; } _material.SetVector("_CameraForward", Camera.current.transform.forward); _material.SetInt("_SampleCount", SampleCount); _material.SetVector("_NoiseVelocity", new Vector4(NoiseVelocity.x, NoiseVelocity.y) * NoiseScale); _material.SetVector("_NoiseData", new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); _material.SetVector("_MieG", new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector("_VolumetricLight", new Vector4(ScatteringCoef, ExtinctionCoef, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture("_CameraDepthTexture", null); _material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Always); if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector("_HeightFog", new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } _commandBuffer.Clear(); int pass = 0; if (!IsCameraInSpotLightBounds()) //离相机太远或者角度很偏时 { pass = 1; } Mesh mesh = VolumetricLightRenderer.GetSpotLightMesh(); //Spot mesh随着range变化缩放 //长度确定为_light.range 宽度由_light.spotAngle决定 float scale = _light.range; float angleScale = Mathf.Tan((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad) * _light.range; Matrix4x4 world = Matrix4x4.TRS(transform.position, transform.rotation, new Vector3(angleScale, angleScale, scale)); Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; Matrix4x4 clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.0f), Quaternion.identity, new Vector3(-0.5f, -0.5f, 1.0f)); //圆形投影区aspect为1 Matrix4x4 proj = Matrix4x4.Perspective(_light.spotAngle, 1, 0, 1); _material.SetMatrix("_MyLightMatrix0", clip * proj * view); _material.SetMatrix("_WorldViewProj", VP * world); _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); Vector3 apex = transform.position; Vector3 axis = transform.forward; // plane equation ax + by + cz + d = 0; precompute d here to lighten the shader Vector3 center = apex + axis * _light.range; float d = -Vector3.Dot(center, axis); // update material _material.SetFloat("_PlaneD", d); _material.SetFloat("_CosAngle", Mathf.Cos((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad)); _material.SetVector("_ConeApex", new Vector4(apex.x, apex.y, apex.z)); _material.SetVector("_ConeAxis", new Vector4(axis.x, axis.y, axis.z)); _material.EnableKeyword("SPOT"); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } if (_light.cookie == null) { _material.SetTexture("_LightTexture0", VolumetricLightRenderer.GetDefaultSpotCookie()); } else { _material.SetTexture("_LightTexture0", _light.cookie); } clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f)); if (_reversedZ) { proj = Matrix4x4.Perspective(_light.spotAngle, 1, _light.range, _light.shadowNearPlane); } else { proj = Matrix4x4.Perspective(_light.spotAngle, 1, _light.shadowNearPlane, _light.range); } Matrix4x4 m = clip * proj; m[0, 2] *= -1; m[1, 2] *= -1; m[2, 2] *= -1; m[3, 2] *= -1; //view = _light.transform.worldToLocalMatrix; _material.SetMatrix("_MyWorld2Shadow", m * view); _material.SetMatrix("_WorldView", m * view); _material.EnableKeyword("SHADOWS_DEPTH"); _commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupPointLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 0; if (!IsCameraInPointLightBounds()) { pass = 2; } _material.SetPass(pass); Mesh mesh = VolumetricLightRenderer.GetPointLightMesh(); _commandBuffer.Clear(); float scale = _light.range * 2.0f; Matrix4x4 world = Matrix4x4.TRS(transform.position, _light.transform.rotation, new Vector3(scale, scale, scale)); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetMatrix("_WorldView", Camera.current.worldToCameraMatrix * world); _material.SetVector("_VolumetricLight", new Vector4(Density, MieG, _light.range, 0)); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); if (_light.cookie == null) { _material.EnableKeyword("POINT"); _material.DisableKeyword("POINT_COOKIE"); } else { Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; _material.SetMatrix("_MyLightMatrix0", view); _material.EnableKeyword("POINT_COOKIE"); _material.DisableKeyword("POINT"); _material.SetTexture("_LightTexture0", _light.cookie); } bool forceShadowsOff = false; if ((_light.transform.position - Camera.current.transform.position).magnitude >= QualitySettings.shadowDistance) { forceShadowsOff = true; } if (_light.shadows != LightShadows.None && forceShadowsOff == false) { _material.EnableKeyword("SHADOWS_CUBE"); _commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer(), BuiltinRenderTextureType.CameraTarget); } else { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); } _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_CUBE"); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 5; _material.SetPass(pass); Mesh mesh = VolumetricLightRenderer.GetPointLightMesh(); _commandBuffer.Clear(); float scale = DirLightFarPlane;// _light.range * 2.0f; Matrix4x4 world = Matrix4x4.TRS(Camera.current.transform.position, Quaternion.identity, new Vector3(scale, scale, scale)); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetMatrix("_WorldView", Camera.current.worldToCameraMatrix * world); _material.SetVector("_VolumetricLight", new Vector4(Density, MieG, _light.range, 0)); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture("_LightTexture0", _light.cookie); } Texture texture = null; if (_light.shadows != LightShadows.None) { _material.EnableKeyword("SHADOWS_DEPTH"); //_commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer(), BuiltinRenderTextureType.CameraTarget); } else { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); } //_commandBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_DEPTH"); //globalBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 4; _material.SetPass(pass); Mesh mesh = VolumetricLightRenderer.GetDirLightMesh(); float zScale = Mathf.Min(Camera.current.farClipPlane * 0.98f, MaxRayLength); float yScale = Camera.current.farClipPlane * Mathf.Tan(Mathf.Deg2Rad * Camera.current.fieldOfView * 0.5f); float xScale = yScale * Camera.current.aspect; Matrix4x4 world = Matrix4x4.TRS(Camera.current.transform.position, Camera.current.transform.rotation, new Vector3(xScale, yScale, zScale)); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetMatrix("_WorldView", Camera.current.worldToCameraMatrix * world); if (Noise) _material.EnableKeyword("NOISE"); else _material.DisableKeyword("NOISE"); _material.SetVector("_LightDir", new Vector4(_light.transform.forward.x, _light.transform.forward.y, _light.transform.forward.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture("_LightTexture0", _light.cookie); } Texture texture = null; if (_light.shadows != LightShadows.None) { _material.EnableKeyword("SHADOWS_DEPTH"); //_commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); //_commandBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } else { _material.DisableKeyword("SHADOWS_DEPTH"); //globalBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupPointLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 0; if (!IsCameraInPointLightBounds()) pass = 2; _material.SetPass(pass); Mesh mesh = VolumetricLightRenderer.GetPointLightMesh(); float scale = _light.range * 2.0f; Matrix4x4 world = Matrix4x4.TRS(transform.position, _light.transform.rotation, new Vector3(scale, scale, scale)); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetMatrix("_WorldView", Camera.current.worldToCameraMatrix * world); if (Noise) _material.EnableKeyword("NOISE"); else _material.DisableKeyword("NOISE"); _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); if (_light.cookie == null) { _material.EnableKeyword("POINT"); _material.DisableKeyword("POINT_COOKIE"); } else { Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; _material.SetMatrix("_MyLightMatrix0", view); _material.EnableKeyword("POINT_COOKIE"); _material.DisableKeyword("POINT"); _material.SetTexture("_LightTexture0", _light.cookie); } bool forceShadowsOff = false; if ((_light.transform.position - Camera.current.transform.position).magnitude >= QualitySettings.shadowDistance) forceShadowsOff = true; if (_light.shadows != LightShadows.None && forceShadowsOff == false) { _material.EnableKeyword("SHADOWS_CUBE"); _commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } else { _material.DisableKeyword("SHADOWS_CUBE"); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupSpotLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); int pass = 1; if (!IsCameraInSpotLightBounds()) { pass = 3; } Mesh mesh = VolumetricLightRenderer.GetSpotLightMesh(); float scale = _light.range; float angleScale = Mathf.Tan((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad) * _light.range; Matrix4x4 world = Matrix4x4.TRS(transform.position, transform.rotation, new Vector3(angleScale, angleScale, scale)); Matrix4x4 view = Matrix4x4.TRS(_light.transform.position, _light.transform.rotation, Vector3.one).inverse; Matrix4x4 clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.0f), Quaternion.identity, new Vector3(-0.5f, -0.5f, 1.0f)); Matrix4x4 proj = Matrix4x4.Perspective(_light.spotAngle, 1, 0, 1); _material.SetMatrix("_MyLightMatrix0", clip * proj * view); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetVector("_LightPos", new Vector4(_light.transform.position.x, _light.transform.position.y, _light.transform.position.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); Vector3 apex = transform.position; Vector3 axis = transform.forward; // plane equation ax + by + cz + d = 0; precompute d here to lighten the shader Vector3 center = apex + axis * _light.range; float d = -Vector3.Dot(center, axis); // update material _material.SetFloat("_PlaneD", d); _material.SetFloat("_CosAngle", Mathf.Cos((_light.spotAngle + 1) * 0.5f * Mathf.Deg2Rad)); _material.SetVector("_ConeApex", new Vector4(apex.x, apex.y, apex.z)); _material.SetVector("_ConeAxis", new Vector4(axis.x, axis.y, axis.z)); _material.EnableKeyword("SPOT"); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } if (_light.cookie == null) { _material.SetTexture("_LightTexture0", VolumetricLightRenderer.GetDefaultSpotCookie()); } else { _material.SetTexture("_LightTexture0", _light.cookie); } bool forceShadowsOff = false; if ((_light.transform.position - Camera.current.transform.position).magnitude >= QualitySettings.shadowDistance) { forceShadowsOff = true; } if (_light.shadows != LightShadows.None && forceShadowsOff == false) { clip = Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f)); if (_reversedZ) { proj = Matrix4x4.Perspective(_light.spotAngle, 1, _light.range, _light.shadowNearPlane); } else { proj = Matrix4x4.Perspective(_light.spotAngle, 1, _light.shadowNearPlane, _light.range); } Matrix4x4 m = clip * proj; m[0, 2] *= -1; m[1, 2] *= -1; m[2, 2] *= -1; m[3, 2] *= -1; //view = _light.transform.worldToLocalMatrix; _material.SetMatrix("_MyWorld2Shadow", m * view); _material.SetMatrix("_WorldView", m * view); _material.EnableKeyword("SHADOWS_DEPTH"); _commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { int pass = 4; _material.SetPass(pass); Mesh mesh = VolumetricLightRenderer.GetDirLightMesh(); _commandBuffer.Clear(); float zScale = Mathf.Min(Camera.current.farClipPlane, MaxRayLength); float yScale = Camera.current.farClipPlane * Mathf.Tan(Mathf.Deg2Rad * Camera.current.fieldOfView * 0.5f); float xScale = yScale * Camera.current.aspect; Matrix4x4 world = Matrix4x4.TRS(Camera.current.transform.position, Camera.current.transform.rotation, new Vector3(xScale, yScale, zScale)); _material.SetMatrix("_WorldViewProj", viewProj * world); _material.SetMatrix("_WorldView", Camera.current.worldToCameraMatrix * world); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } _material.SetVector("_LightDir", new Vector4(_light.transform.forward.x, _light.transform.forward.y, _light.transform.forward.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture("_LightTexture0", _light.cookie); } Texture texture = null; if (_light.shadows != LightShadows.None) { _material.EnableKeyword("SHADOWS_DEPTH"); //_commandBuffer.SetGlobalTexture("_ShadowMapTexture", BuiltinRenderTextureType.CurrentActive); if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer(), BuiltinRenderTextureType.CameraTarget); } else { _commandBuffer.SetRenderTarget(renderer.GetVolumeLightBuffer()); } //_commandBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); _commandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_DEPTH"); //globalBuffer.Blit(texture, VolumetricLightRenderer.GetVolumeLightBuffer(), _material, pass); renderer.GlobalCommandBuffer.DrawMesh(mesh, world, _material, 0, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
private void SetupSpotLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { this._commandBuffer.Clear(); int num1 = 1; if (!this.IsCameraInSpotLightBounds()) { num1 = 3; } Mesh spotLightMesh = VolumetricLightRenderer.GetSpotLightMesh(); float range = this._light.get_range(); float num2 = Mathf.Tan((float)(((double)this._light.get_spotAngle() + 1.0) * 0.5 * (Math.PI / 180.0))) * this._light.get_range(); Matrix4x4 matrix4x4_1 = Matrix4x4.TRS(((Component)this).get_transform().get_position(), ((Component)this).get_transform().get_rotation(), new Vector3(num2, num2, range)); Matrix4x4 matrix4x4_2 = Matrix4x4.TRS(((Component)this._light).get_transform().get_position(), ((Component)this._light).get_transform().get_rotation(), Vector3.get_one()); Matrix4x4 inverse = ((Matrix4x4) ref matrix4x4_2).get_inverse(); this._material.SetMatrix("_MyLightMatrix0", Matrix4x4.op_Multiply(Matrix4x4.op_Multiply(Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.0f), Quaternion.get_identity(), new Vector3(-0.5f, -0.5f, 1f)), Matrix4x4.Perspective(this._light.get_spotAngle(), 1f, 0.0f, 1f)), inverse)); this._material.SetMatrix("_WorldViewProj", Matrix4x4.op_Multiply(viewProj, matrix4x4_1)); this._material.SetVector("_LightPos", new Vector4((float)((Component)this._light).get_transform().get_position().x, (float)((Component)this._light).get_transform().get_position().y, (float)((Component)this._light).get_transform().get_position().z, (float)(1.0 / ((double)this._light.get_range() * (double)this._light.get_range())))); this._material.SetVector("_LightColor", Color.op_Implicit(Color.op_Multiply(this._light.get_color(), this._light.get_intensity()))); Vector3 position = ((Component)this).get_transform().get_position(); Vector3 forward = ((Component)this).get_transform().get_forward(); this._material.SetFloat("_PlaneD", -Vector3.Dot(Vector3.op_Addition(position, Vector3.op_Multiply(forward, this._light.get_range())), forward)); this._material.SetFloat("_CosAngle", Mathf.Cos((float)(((double)this._light.get_spotAngle() + 1.0) * 0.5 * (Math.PI / 180.0)))); this._material.SetVector("_ConeApex", new Vector4((float)position.x, (float)position.y, (float)position.z)); this._material.SetVector("_ConeAxis", new Vector4((float)forward.x, (float)forward.y, (float)forward.z)); this._material.EnableKeyword("SPOT"); if (this.Noise) { this._material.EnableKeyword("NOISE"); } else { this._material.DisableKeyword("NOISE"); } if (Object.op_Equality((Object)this._light.get_cookie(), (Object)null)) { this._material.SetTexture("_LightTexture0", VolumetricLightRenderer.GetDefaultSpotCookie()); } else { this._material.SetTexture("_LightTexture0", this._light.get_cookie()); } bool flag = false; Vector3 vector3 = Vector3.op_Subtraction(((Component)this._light).get_transform().get_position(), ((Component)Camera.get_current()).get_transform().get_position()); if ((double)((Vector3) ref vector3).get_magnitude() >= (double)QualitySettings.get_shadowDistance()) { flag = true; } if (this._light.get_shadows() != null && !flag) { Matrix4x4 matrix4x4_3 = Matrix4x4.op_Multiply(Matrix4x4.TRS(new Vector3(0.5f, 0.5f, 0.5f), Quaternion.get_identity(), new Vector3(0.5f, 0.5f, 0.5f)), !this._reversedZ ? Matrix4x4.Perspective(this._light.get_spotAngle(), 1f, this._light.get_shadowNearPlane(), this._light.get_range()) : Matrix4x4.Perspective(this._light.get_spotAngle(), 1f, this._light.get_range(), this._light.get_shadowNearPlane())); // ISSUE: variable of a reference type Matrix4x4& local1; ((Matrix4x4)(local1 = ref matrix4x4_3)).set_Item(0, 2, ((Matrix4x4) ref local1).get_Item(0, 2) * -1f); // ISSUE: variable of a reference type Matrix4x4& local2; ((Matrix4x4)(local2 = ref matrix4x4_3)).set_Item(1, 2, ((Matrix4x4) ref local2).get_Item(1, 2) * -1f); // ISSUE: variable of a reference type Matrix4x4& local3; ((Matrix4x4)(local3 = ref matrix4x4_3)).set_Item(2, 2, ((Matrix4x4) ref local3).get_Item(2, 2) * -1f); // ISSUE: variable of a reference type Matrix4x4& local4; ((Matrix4x4)(local4 = ref matrix4x4_3)).set_Item(3, 2, ((Matrix4x4) ref local4).get_Item(3, 2) * -1f); this._material.SetMatrix("_MyWorld2Shadow", Matrix4x4.op_Multiply(matrix4x4_3, inverse)); this._material.SetMatrix("_WorldView", Matrix4x4.op_Multiply(matrix4x4_3, inverse)); this._material.EnableKeyword("SHADOWS_DEPTH"); this._commandBuffer.SetGlobalTexture("_ShadowMapTexture", RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)1)); this._commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((Texture)renderer.GetVolumeLightBuffer())); this._commandBuffer.DrawMesh(spotLightMesh, matrix4x4_1, this._material, 0, num1); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, this._commandBuffer, viewProj); } else { this._material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.DrawMesh(spotLightMesh, matrix4x4_1, this._material, 0, num1); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
private void SetupPointLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { this._commandBuffer.Clear(); int num1 = 0; if (!this.IsCameraInPointLightBounds()) { num1 = 2; } this._material.SetPass(num1); Mesh pointLightMesh = VolumetricLightRenderer.GetPointLightMesh(); float num2 = this._light.get_range() * 2f; Matrix4x4 matrix4x4_1 = Matrix4x4.TRS(((Component)this).get_transform().get_position(), ((Component)this._light).get_transform().get_rotation(), new Vector3(num2, num2, num2)); this._material.SetMatrix("_WorldViewProj", Matrix4x4.op_Multiply(viewProj, matrix4x4_1)); this._material.SetMatrix("_WorldView", Matrix4x4.op_Multiply(Camera.get_current().get_worldToCameraMatrix(), matrix4x4_1)); if (this.Noise) { this._material.EnableKeyword("NOISE"); } else { this._material.DisableKeyword("NOISE"); } this._material.SetVector("_LightPos", new Vector4((float)((Component)this._light).get_transform().get_position().x, (float)((Component)this._light).get_transform().get_position().y, (float)((Component)this._light).get_transform().get_position().z, (float)(1.0 / ((double)this._light.get_range() * (double)this._light.get_range())))); this._material.SetColor("_LightColor", Color.op_Multiply(this._light.get_color(), this._light.get_intensity())); if (Object.op_Equality((Object)this._light.get_cookie(), (Object)null)) { this._material.EnableKeyword("POINT"); this._material.DisableKeyword("POINT_COOKIE"); } else { Matrix4x4 matrix4x4_2 = Matrix4x4.TRS(((Component)this._light).get_transform().get_position(), ((Component)this._light).get_transform().get_rotation(), Vector3.get_one()); this._material.SetMatrix("_MyLightMatrix0", ((Matrix4x4) ref matrix4x4_2).get_inverse()); this._material.EnableKeyword("POINT_COOKIE"); this._material.DisableKeyword("POINT"); this._material.SetTexture("_LightTexture0", this._light.get_cookie()); } bool flag = false; Vector3 vector3 = Vector3.op_Subtraction(((Component)this._light).get_transform().get_position(), ((Component)Camera.get_current()).get_transform().get_position()); if ((double)((Vector3) ref vector3).get_magnitude() >= (double)QualitySettings.get_shadowDistance()) { flag = true; } if (this._light.get_shadows() != null && !flag) { this._material.EnableKeyword("SHADOWS_CUBE"); this._commandBuffer.SetGlobalTexture("_ShadowMapTexture", RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)1)); this._commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((Texture)renderer.GetVolumeLightBuffer())); this._commandBuffer.DrawMesh(pointLightMesh, matrix4x4_1, this._material, 0, num1); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, this._commandBuffer, viewProj); } else { this._material.DisableKeyword("SHADOWS_CUBE"); renderer.GlobalCommandBuffer.DrawMesh(pointLightMesh, matrix4x4_1, this._material, 0, num1); if (this.CustomRenderEvent == null) { return; } this.CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void SetupDirectionalLight(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { _commandBuffer.Clear(); int pass = 4; _material.SetPass(pass); if (Noise) { _material.EnableKeyword("NOISE"); } else { _material.DisableKeyword("NOISE"); } _material.SetVector("_LightDir", new Vector4(_light.transform.forward.x, _light.transform.forward.y, _light.transform.forward.z, 1.0f / (_light.range * _light.range))); _material.SetVector("_LightColor", _light.color * _light.intensity); _material.SetFloat("_MaxRayLength", MaxRayLength); if (_light.cookie == null) { _material.EnableKeyword("DIRECTIONAL"); _material.DisableKeyword("DIRECTIONAL_COOKIE"); } else { _material.EnableKeyword("DIRECTIONAL_COOKIE"); _material.DisableKeyword("DIRECTIONAL"); _material.SetTexture("_LightTexture0", _light.cookie); } // setup frustum corners for world position reconstruction // bottom left _frustumCorners[0] = Camera.current.ViewportToWorldPoint(new Vector3(0, 0, Camera.current.farClipPlane)); // top left _frustumCorners[2] = Camera.current.ViewportToWorldPoint(new Vector3(0, 1, Camera.current.farClipPlane)); // top right _frustumCorners[3] = Camera.current.ViewportToWorldPoint(new Vector3(1, 1, Camera.current.farClipPlane)); // bottom right _frustumCorners[1] = Camera.current.ViewportToWorldPoint(new Vector3(1, 0, Camera.current.farClipPlane)); #if UNITY_5_4_OR_NEWER _material.SetVectorArray("_FrustumCorners", _frustumCorners); #else _material.SetVector("_FrustumCorners0", _frustumCorners[0]); _material.SetVector("_FrustumCorners1", _frustumCorners[1]); _material.SetVector("_FrustumCorners2", _frustumCorners[2]); _material.SetVector("_FrustumCorners3", _frustumCorners[3]); #endif Texture nullTexture = null; if (_light.shadows != LightShadows.None) { _material.EnableKeyword("SHADOWS_DEPTH"); _commandBuffer.Blit(nullTexture, renderer.GetVolumeLightBuffer(), _material, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, _commandBuffer, viewProj); } } else { _material.DisableKeyword("SHADOWS_DEPTH"); renderer.GlobalCommandBuffer.Blit(nullTexture, renderer.GetVolumeLightBuffer(), _material, pass); if (CustomRenderEvent != null) { CustomRenderEvent(renderer, this, renderer.GlobalCommandBuffer, viewProj); } } }
/// <summary> /// /// </summary> /// <param name="renderer"></param> /// <param name="viewProj"></param> private void VolumetricLightRenderer_PreRenderEvent(VolumetricLightRenderer renderer, Matrix4x4 viewProj) { if (!_light.gameObject.activeInHierarchy) return; _material.SetVector("_CameraForward", Camera.current.transform.forward); _material.SetInt("_SampleCount", SampleCount); _material.SetVector("_NoiseVelocity", new Vector4(NoiseVelocity.x, NoiseVelocity.y) * NoiseScale); _material.SetVector("_NoiseData", new Vector4(NoiseScale, NoiseIntensity, NoiseIntensityOffset)); _material.SetVector("_MieG", new Vector4(1 - (MieG * MieG), 1 + (MieG * MieG), 2 * MieG, 1.0f / (4.0f * Mathf.PI))); _material.SetVector("_VolumetricLight", new Vector4(ScatteringCoef, ExtinctionCoef, _light.range, 1.0f - SkyboxExtinctionCoef)); _material.SetTexture("_CameraDepthTexture", renderer.GetVolumeLightDepthBuffer()); //if (renderer.Resolution == VolumetricLightRenderer.VolumtericResolution.Full) { //_material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.LessEqual); //_material.DisableKeyword("MANUAL_ZTEST"); } //else { _material.SetFloat("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Always); // downsampled light buffer can't use native zbuffer for ztest, try to perform ztest in pixel shader to avoid ray marching for occulded geometry //_material.EnableKeyword("MANUAL_ZTEST"); } if (HeightFog) { _material.EnableKeyword("HEIGHT_FOG"); _material.SetVector("_HeightFog", new Vector4(GroundLevel, HeightScale)); } else { _material.DisableKeyword("HEIGHT_FOG"); } if(_light.type == LightType.Point) { SetupPointLight(renderer, viewProj); } else if(_light.type == LightType.Spot) { SetupSpotLight(renderer, viewProj); } else if (_light.type == LightType.Directional) { SetupDirectionalLight(renderer, viewProj); } }