Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/UltimateWater/WaterSubsurfaceScattering.cs
2026-02-21 16:45:37 +08:00

207 lines
6.5 KiB
C#

using System;
using System.Collections.Generic;
using UltimateWater.Internal;
using UnityEngine;
namespace UltimateWater
{
[Serializable]
public sealed class WaterSubsurfaceScattering : WaterModule
{
[Serializable]
public enum SubsurfaceScatteringMode
{
Disabled = 0,
TextureSpace = 1
}
[SerializeField]
private SubsurfaceScatteringMode _Mode = SubsurfaceScatteringMode.TextureSpace;
[SerializeField]
private BlurSSS _SubsurfaceScatteringBlur;
[SerializeField]
[Range(0f, 0.9f)]
private float _IgnoredLightFraction = 0.15f;
[Resolution(128, new int[] { 64, 128, 256, 512 })]
[SerializeField]
private int _AmbientResolution = 128;
[Range(-1f, 6f)]
[SerializeField]
private int _LightCount = -1;
[SerializeField]
private int _LightingLayer = 22;
private RenderTexture _ScatteringTex;
private Vector4 _ShaderParams;
private Water _Water;
private static readonly List<Water> _CachedRenderList;
public float IsotropicScatteringIntensity
{
get
{
return _ShaderParams.x;
}
set
{
_ShaderParams.x = value;
}
}
public float SubsurfaceScatteringContrast
{
get
{
return _ShaderParams.y;
}
set
{
_ShaderParams.y = value;
}
}
static WaterSubsurfaceScattering()
{
_CachedRenderList = new List<Water> { null };
}
internal override void OnWaterRender(WaterCamera waterCamera)
{
Camera cameraComponent = waterCamera.CameraComponent;
Rect localMapsRect = waterCamera.LocalMapsRect;
if (localMapsRect.width != 0f && Application.isPlaying && _Mode != SubsurfaceScatteringMode.Disabled)
{
RenderTexture temporary = RenderTexture.GetTemporary(_AmbientResolution, _AmbientResolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
temporary.filterMode = FilterMode.Bilinear;
Camera effectsCamera = waterCamera.EffectsCamera;
WaterCamera component = effectsCamera.GetComponent<WaterCamera>();
component.enabled = true;
component.GeometryType = WaterGeometryType.UniformGrid;
_CachedRenderList[0] = _Water;
component.SetCustomWaterRenderList(_CachedRenderList);
effectsCamera.stereoTargetEye = StereoTargetEyeMask.None;
effectsCamera.enabled = false;
effectsCamera.depthTextureMode = DepthTextureMode.None;
effectsCamera.renderingPath = RenderingPath.Forward;
effectsCamera.orthographic = true;
effectsCamera.orthographicSize = localMapsRect.width * 0.5f;
effectsCamera.cullingMask = 1 << _LightingLayer;
effectsCamera.farClipPlane = 2000f;
effectsCamera.ResetProjectionMatrix();
effectsCamera.clearFlags = CameraClearFlags.Nothing;
effectsCamera.allowHDR = true;
effectsCamera.transform.position = new Vector3(localMapsRect.center.x, 1000f, localMapsRect.center.y);
effectsCamera.transform.rotation = Quaternion.LookRotation(new Vector3(0f, -1f, 0f), new Vector3(0f, 0f, 1f));
effectsCamera.targetTexture = temporary;
Shader.SetGlobalVector("_ScatteringParams", _ShaderParams);
Shader.SetGlobalVector("_WorldSpaceOriginalCameraPos", cameraComponent.transform.position);
int pixelLightCount = 3;
if (_LightCount >= 0)
{
pixelLightCount = QualitySettings.pixelLightCount;
QualitySettings.pixelLightCount = _LightCount;
}
Shader shader = ShaderUtility.Instance.Get(ShaderList.CollectLight);
_Water.gameObject.layer = _LightingLayer;
effectsCamera.RenderWithShader(shader, "CustomType");
_Water.gameObject.layer = WaterProjectSettings.Instance.WaterLayer;
if (_LightCount >= 0)
{
QualitySettings.pixelLightCount = pixelLightCount;
}
component.GeometryType = WaterGeometryType.Auto;
component.SetCustomWaterRenderList(null);
RenderTexture temporary2 = RenderTexture.GetTemporary(_AmbientResolution, _AmbientResolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
temporary2.filterMode = FilterMode.Point;
Color parameterValue = _Water.Materials.GetParameterValue(WaterMaterials.ColorParameter.AbsorptionColor);
_SubsurfaceScatteringBlur.BlurMaterial.SetVector("_ScatteringParams", _ShaderParams);
_SubsurfaceScatteringBlur.Apply(temporary, temporary2, parameterValue, waterCamera.LocalMapsRect.width, _IgnoredLightFraction);
RenderTexture.ReleaseTemporary(temporary);
Graphics.Blit(temporary2, _ScatteringTex, _SubsurfaceScatteringBlur.BlurMaterial, 1);
RenderTexture.ReleaseTemporary(temporary2);
_Water.Renderer.PropertyBlock.SetTexture("_SubsurfaceScattering", _ScatteringTex);
Graphics.SetRenderTarget(null);
}
}
internal override void Start(Water water)
{
_Water = water;
water.ProfilesManager.Changed.AddListener(ResolveProfileData);
}
internal override void Enable()
{
Validate();
if (Application.isPlaying && _Mode == SubsurfaceScatteringMode.TextureSpace)
{
_ScatteringTex = new RenderTexture(_AmbientResolution, _AmbientResolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear)
{
name = "[UWS] WaterSubsurfaceScattering - Scattering Tex",
hideFlags = HideFlags.DontSave,
filterMode = FilterMode.Bilinear,
useMipMap = WaterProjectSettings.Instance.AllowFloatingPointMipMaps,
autoGenerateMips = WaterProjectSettings.Instance.AllowFloatingPointMipMaps
};
}
}
internal override void Disable()
{
if (_ScatteringTex != null)
{
_ScatteringTex.Destroy();
_ScatteringTex = null;
}
if (_Water != null)
{
Texture2D texture2D = DefaultTextures.Get(Color.white);
if (texture2D != null)
{
_Water.Renderer.PropertyBlock.SetTexture("_SubsurfaceScattering", texture2D);
}
}
}
internal override void Destroy()
{
if (!(_Water == null))
{
_Water.ProfilesManager.Changed.RemoveListener(ResolveProfileData);
}
}
private void ResolveProfileData(Water water)
{
Water.WeightedProfile[] profiles = water.ProfilesManager.Profiles;
_ShaderParams.x = 0f;
_ShaderParams.y = 0f;
for (int i = 0; i < profiles.Length; i++)
{
WaterProfileData profile = profiles[i].Profile;
float weight = profiles[i].Weight;
_ShaderParams.x += profile.IsotropicScatteringIntensity * weight;
_ShaderParams.y += profile.SubsurfaceScatteringContrast * weight;
}
_ShaderParams.x *= 1f + _ShaderParams.y;
}
internal override void Validate()
{
if (_SubsurfaceScatteringBlur == null)
{
_SubsurfaceScatteringBlur = new BlurSSS();
}
_SubsurfaceScatteringBlur.Validate("UltimateWater/Utilities/Blur (Subsurface Scattering)", "Shaders/Blurs", 6);
}
}
}