(Update) Clean Projet

This commit is contained in:
2026-06-24 14:38:51 +02:00
parent 48588ccfed
commit ef01552268
2629 changed files with 1523 additions and 430219 deletions
@@ -0,0 +1,233 @@
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
#if URP
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.Universal;
namespace StylizedWater3
{
public class HeightPrePass : ScriptableRenderPass
{
private const string profilerTag = "Water Height Prepass";
private static readonly ProfilingSampler profilerSampler = new ProfilingSampler(profilerTag);
/// <summary>
/// Using this as a value comparison in shader code to determine if not water is being hit
/// </summary>
public const float VOID_THRESHOLD = -1000f;
private static readonly Color targetClearColor = new Color(VOID_THRESHOLD, 0, 0, 0);
[Serializable]
public class Settings
{
public bool enable = true;
public float range = 500f;
[Range(1f, 8f)]
public int cellsPerUnit = 4;
public int maxResolution = 4096;
[Tooltip("[When in Play mode] Skips processing the height prepass for the scene-view camera. This helps keep the rendering centered around the main camera when in Play mode.")]
public bool disableInSceneView = true;
/// <summary>
/// Returns the enabled state, either from the settings or if forced because it is required by other functionality
/// </summary>
public bool isEnabled => enable || StylizedWaterRenderFeature.RequireHeightPrePass || HeightQuerySystem.RequiresHeightPrepass;
}
//Render pass
FilteringSettings m_FilteringSettings;
RenderStateBlock m_RenderStateBlock;
private readonly List<ShaderTagId> m_ShaderTagIdList = new List<ShaderTagId>()
{
new (ShaderParams.LightModes.WaterHeight)
};
public HeightPrePass()
{
m_FilteringSettings = new FilteringSettings(RenderQueueRange.all, LayerMask.GetMask("Water"));
m_RenderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
}
public const string BufferName = "_WaterHeightBuffer";
public static readonly int _WaterHeightBuffer = Shader.PropertyToID(BufferName);
private const string CoordsName = "_WaterHeightCoords";
private static readonly int _WaterHeightCoords = Shader.PropertyToID(CoordsName);
public static readonly int _WaterHeightPrePassAvailable = Shader.PropertyToID("_WaterHeightPrePassAvailable");
private int resolution;
private int m_resolution;
private Settings settings;
private RendererListParams rendererListParams;
private RendererList rendererList;
public sealed class RenderTargetDebugContext : RenderTargetDebugger.RenderTarget
{
public RenderTargetDebugContext()
{
this.name = "Height Buffer";
this.description = "Water geometry height (red channel). Height displacement from effects (green channel)." +
"\n\nUsed by: Water decals, GPU-based buoyancy";
this.textureName = BufferName;
this.propertyID = _WaterHeightBuffer;
this.order = 0;
}
}
public void Setup(Settings settings)
{
this.settings = settings;
resolution = PlanarProjection.CalculateResolution(settings.range, settings.cellsPerUnit, 16, settings.maxResolution);
}
public class FrameData : ContextItem
{
public TextureHandle _WaterHeightBuffer;
public override void Reset()
{
_WaterHeightBuffer = TextureHandle.nullHandle;
}
}
private class PassData
{
public RendererListHandle rendererListHandle;
public TextureHandle renderTarget;
public PlanarProjection planarProjection;
public Vector4 rendererCoords;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameContext)
{
var renderingData = frameContext.Get<UniversalRenderingData>();
var cameraData = frameContext.Get<UniversalCameraData>();
var lightData = frameContext.Get<UniversalLightData>();
DrawingSettings drawingSettings = CreateDrawingSettings(m_ShaderTagIdList, renderingData, cameraData, lightData, SortingCriteria.RenderQueue | SortingCriteria.SortingLayer | SortingCriteria.CommonTransparent);
drawingSettings.perObjectData = PerObjectData.None;
rendererListParams.cullingResults = renderingData.cullResults;
rendererListParams.drawSettings = drawingSettings;
rendererListParams.filteringSettings = m_FilteringSettings;
using(var builder = renderGraph.AddRasterRenderPass<PassData>("Water Height Pre-pass", out var passData))
{
//Render target
RenderTextureDescriptor renderTargetDescriptor = new RenderTextureDescriptor(resolution, resolution, GraphicsFormat.R16G16_SFloat, 0);
passData.renderTarget = UniversalRenderer.CreateRenderGraphTexture(renderGraph, renderTargetDescriptor, BufferName + cameraData.camera.name, true, FilterMode.Bilinear, TextureWrapMode.Clamp);
//Store render target in RG, so it can be retrieved in other passes
FrameData frameData = frameContext.GetOrCreate<FrameData>();
frameData._WaterHeightBuffer = passData.renderTarget;
//Mark the texture as readable
//builder.UseTexture(passData.renderTarget, AccessFlags.ReadWrite);
#if UNITY_EDITOR || DEVELOPMENT_BUILD
if (RenderTargetDebugger.InspectedProperty == _WaterHeightBuffer)
{
StylizedWaterRenderFeature.DebugData debugData = frameContext.Get<StylizedWaterRenderFeature.DebugData>();
debugData.currentHandle = passData.renderTarget;
}
#endif
passData.rendererListHandle = renderGraph.CreateRendererList(rendererListParams);
passData.planarProjection = new PlanarProjection
{
center = cameraData.camera.transform.position,
scale = settings.range,
offset = cameraData.camera.transform.forward * ((settings.range * 0.5f) - 5),
resolution = resolution
};
passData.planarProjection.Recalculate();
passData.planarProjection.SetUV(ref passData.rendererCoords);
//Set render target and bind to global property
builder.SetRenderAttachment(passData.renderTarget, 0, AccessFlags.Write);
//builder.CreateTransientTexture(passData.renderTarget);
builder.SetGlobalTextureAfterPass(passData.renderTarget, _WaterHeightBuffer);
builder.UseRendererList(passData.rendererListHandle);
builder.AllowGlobalStateModification(true);
builder.AllowPassCulling(false);
builder.SetRenderFunc((PassData data, RasterGraphContext context) =>
{
Execute(context, data);
});
}
}
private readonly int _WorldSpaceCameraPos = Shader.PropertyToID("_WorldSpaceCameraPos");
private void Execute(RasterGraphContext context, PassData data)
{
var cmd = context.cmd;
using (new ProfilingScope(cmd, profilerSampler))
{
cmd.ClearRenderTarget(true, true, targetClearColor);
cmd.SetGlobalInt(_WaterHeightPrePassAvailable, 1);
cmd.EnableShaderKeyword(ShaderParams.Keywords.WaterHeightPass);
cmd.SetViewProjectionMatrices(data.planarProjection.view, data.planarProjection.projection);
//RenderingUtils.SetViewAndProjectionMatrices(cmd, data.planarProjection.view, data.planarProjection.projection, true);
cmd.SetViewport(data.planarProjection.viewportRect);
//Is this still needed?
//cmd.SetGlobalMatrix("UNITY_MATRIX_V", data.view);
cmd.SetGlobalVector(_WaterHeightCoords, data.rendererCoords);
//Bug? During this pass the camera position sent to shaderland is that of the scene-view camera (if the tab is open)
//Possibly the value from the previous frame/camera. This breaks distance-based effects such as waves.
//Force an updated value
cmd.SetGlobalVector(_WorldSpaceCameraPos, data.planarProjection.center);
cmd.DrawRendererList(data.rendererListHandle);
//Reset (breaks VR!)
//cmd.SetViewProjectionMatrices(data.ViewMatrix, data.GPUProjectionMatrix);
}
}
public override void OnCameraCleanup(CommandBuffer cmd)
{
cmd.SetGlobalVector(_WaterHeightCoords, Vector4.zero);
cmd.SetGlobalInt(_WaterHeightPrePassAvailable, 0);
cmd.DisableShaderKeyword(ShaderParams.Keywords.WaterHeightPass);
}
public void Dispose()
{
}
#if !UNITY_6000_4_OR_NEWER
#pragma warning disable CS0672
#pragma warning disable CS0618
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { }
#pragma warning restore CS0672
#pragma warning restore CS0618
#endif
}
}
#endif
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 994d894f45c86bd4791e3353806d7175
timeCreated: 1701077223
AssetOrigin:
serializedVersion: 1
productId: 287769
packageName: Stylized Water 3
packageVersion: 3.2.6
assetPath: Assets/Stylized Water 3/Runtime/Rendering/HeightPrePass.cs
uploadId: 895866
@@ -0,0 +1,601 @@
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
#if URP
using UnityEngine.Rendering.Universal;
#endif
namespace StylizedWater3
{
[ExecuteInEditMode]
[AddComponentMenu("Stylized Water 3/Planar Reflection Renderer")]
[HelpURL("https://staggart.xyz/unity/stylized-water-3/sw3-docs/?section=reflection-rendering")]
public class PlanarReflectionRenderer : MonoBehaviour
{
#if URP
public static List<PlanarReflectionRenderer> Instances = new List<PlanarReflectionRenderer>();
[NonSerialized]
public Dictionary<Camera, Camera> reflectionCameras = new Dictionary<Camera, Camera>();
//Rendering
[Tooltip("If enabled, the reflection plane will be based on this transform's up vector (green arrow).\n\nOtherwise the world's upwards direction is assumed")]
public bool rotatable = false;
[Tooltip("Set the layers that should be rendered into the reflection. The \"Water\" layer is always excluded")]
public LayerMask cullingMask = -1;
[Tooltip("The renderer used by the reflection camera. It's recommend to create a separate renderer, so any custom render features aren't executed for the reflection")]
public int rendererIndex = -1;
[Min(0f)]
public float offset = 0.05f;
[Tooltip("When disabled, the skybox reflection comes from a Reflection Probe. This has the benefit of being omni-directional rather than flat/planar. Enabled this to render the skybox into the planar reflection anyway." +
"\n\nNote that enabling this will override Screen Space Reflections completely!")]
public bool includeSkybox;
[Tooltip("Render Unity's default scene fog in the reflection. Note that this doesn't strictly work correctly on large triangles, as it is incompatible with oblique camera projections." +
"\n\n" +
"This does not include to post-processing fog effects!")]
public bool enableFog;
[Tooltip("Also render for the scene-view camera. This may be prone to some issues, such a console errors.")]
public bool enableInSceneView = true;
//Quality
public bool renderShadows;
[Range(0.25f, 1f)]
[Tooltip("A multiplier for the rendering resolution, based on the current screen resolution. The render scale, as configured in the pipeline settings is multiplied over this.")]
public float renderScale = 0.75f;
[Range(0, 4)]
[Tooltip("Do not render LOD objects lower than this value. Example: With a value of 1, LOD0 for LOD Groups will not be used")]
public int maximumLODLevel = 0;
[SerializeField]
public List<WaterObject> waterObjects = new List<WaterObject>();
[Tooltip("If enabled, the center of the rendering bounds (that wraps around the water objects) moves with the Transform position" +
"\n\nYou must however ensure you are only moving on the XZ axis")]
public bool moveWithTransform;
[HideInInspector]
public Bounds bounds = new Bounds();
private float m_renderScale = 1f;
/// <summary>
/// Reflections will only render if this is true. Value can be set through the static SetQuality function
/// </summary>
public static bool AllowReflections { get; private set; } = true;
private static readonly int _PlanarReflectionsEnabledID = Shader.PropertyToID("_PlanarReflectionsEnabled");
private static readonly int _PlanarReflectionID = Shader.PropertyToID("_PlanarReflection");
private UniversalRenderPipeline.SingleCameraRequest requestData;
[NonSerialized]
public bool isRendering;
private Camera m_reflectionCamera;
private static UniversalAdditionalCameraData m_cameraData;
private bool isUnderwater;
private void Reset()
{
this.gameObject.name = "Planar Reflection Renderer";
}
private void OnEnable()
{
InitializeValues();
Instances.Add(this);
EnableReflections();
}
private void OnDisable()
{
Instances.Remove(this);
DisableReflections();
}
public void InitializeValues()
{
m_renderScale = renderScale;
}
/// <summary>
/// Assigns all Water Objects in the WaterObject.Instances list and enables reflection for them
/// </summary>
public void ApplyToAllWaterInstances()
{
waterObjects = new List<WaterObject>(WaterObject.Instances);
RecalculateBounds();
EnableMaterialReflectionSampling();
}
[Obsolete("renderRange parameter has been deprecated. Use the SetQuality overload with this argument instead.")]
public static void SetQuality(bool enableReflections, float renderScale = -1f, float renderRange = -1f, int maxLodLevel = -1) { }
/// <summary>
/// Toggle reflections or set the render scale for all reflection renderers. This can be tied into performance scaling or graphics settings in menus
/// </summary>
/// <param name="enableReflections">Toggles rendering of reflections, and toggles it on all the assigned water objects</param>
/// <param name="renderScale">A multiplier for the current screen resolution. Note that the render scale configured in URP is also taken into account</param>
public static void SetQuality(bool enableReflections, float renderScale = -1f, int maxLodLevel = -1)
{
AllowReflections = enableReflections;
foreach (PlanarReflectionRenderer renderer in Instances)
{
if (renderScale > 0) renderer.renderScale = renderScale;
if (maxLodLevel >= 0) renderer.maximumLODLevel = maxLodLevel;
renderer.InitializeValues();
if (enableReflections) renderer.EnableReflections();
if (!enableReflections) renderer.DisableReflections();
}
}
public void EnableReflections()
{
if (!AllowReflections || PipelineUtilities.VREnabled()) return;
RenderPipelineManager.beginCameraRendering += OnWillRenderCamera;
ToggleMaterialReflectionSampling(true);
}
public void DisableReflections()
{
RenderPipelineManager.beginCameraRendering -= OnWillRenderCamera;
ToggleMaterialReflectionSampling(false);
//Clear cameras
foreach (var kvp in reflectionCameras)
{
if (kvp.Value == null) continue;
if (kvp.Value)
{
RenderTexture.ReleaseTemporary(kvp.Value.targetTexture);
DestroyImmediate(kvp.Value.gameObject);
}
}
reflectionCameras.Clear();
}
private void OnDrawGizmosSelected()
{
Gizmos.color = bounds.size.y > 0.01f ? Color.yellow : Color.white;
Gizmos.DrawWireCube(bounds.center, bounds.size);
}
public Bounds CalculateBounds()
{
Bounds m_bounds = new Bounds(Vector3.zero, Vector3.zero);
if (waterObjects == null) return m_bounds;
if (waterObjects.Count == 0) return m_bounds;
Vector3 minSum = Vector3.one * Mathf.Infinity;
Vector3 maxSum = Vector3.one * Mathf.NegativeInfinity;
for (int i = 0; i < waterObjects.Count; i++)
{
if (!waterObjects[i]) continue;
minSum = Vector3.Min(waterObjects[i].meshRenderer.bounds.min, minSum);
maxSum = Vector3.Max(waterObjects[i].meshRenderer.bounds.max, maxSum);
}
m_bounds.SetMinMax(minSum, maxSum);
//Flatten to center
m_bounds.size = new Vector3(m_bounds.size.x, 0f, m_bounds.size.z);
return m_bounds;
}
public void RecalculateBounds()
{
bounds = CalculateBounds();
}
public bool InvalidContext(Camera targetCamera)
{
//Definitely reject any reflection cameras!
if (targetCamera.hideFlags == HideFlags.DontSave) return true;
CameraType cameraType = targetCamera.cameraType;
#if UNITY_EDITOR
if (enableInSceneView == false && cameraType == CameraType.SceneView) return true;
//During the compilation of shaders reflection rendering is prone to causing issue, and can break the render pipeline
if(UnityEditor.ShaderUtil.anythingCompiling) return true;
//Avoid the "Screen position outside of frustrum" error
if (targetCamera.orthographic && Vector3.Dot(Vector3.up, targetCamera.transform.up) > 0.9999f) return true;
//Causes an internal error in URP's rendering code in the CopyColorPass
if (targetCamera.cameraType == CameraType.SceneView && UnityEditor.SceneView.lastActiveSceneView && UnityEditor.SceneView.lastActiveSceneView.isUsingSceneFiltering) return true;
#endif
//Skip for any special use camera's (except scene view camera)
//Note: Scene camera still rendering even if window not focused!
return (cameraType != CameraType.SceneView && (cameraType == CameraType.Reflection || cameraType == CameraType.Preview || hideFlags != HideFlags.None));
}
private void OnWillRenderCamera(ScriptableRenderContext context, Camera camera)
{
if (InvalidContext(camera))
{
isRendering = false;
return;
}
isRendering = WaterObjectsVisible(camera);
if (isRendering == false) return;
if (moveWithTransform) bounds.center = this.transform.position;
m_cameraData = camera.GetComponent<UniversalAdditionalCameraData>();
if (m_cameraData && m_cameraData.renderType == CameraRenderType.Overlay) return;
reflectionCameras.TryGetValue(camera, out m_reflectionCamera);
if (m_reflectionCamera == null) CreateReflectionCamera(camera);
//It's possible it is destroyed at this point when disabling reflections
if (!m_reflectionCamera) return;
UnityEngine.Profiling.Profiler.BeginSample("Planar Water Reflections", camera);
//Render scale changed
if (Math.Abs(renderScale - m_renderScale) > 0.001f)
{
RenderTexture.ReleaseTemporary(m_reflectionCamera.targetTexture);
CreateRenderTexture(m_reflectionCamera, camera);
m_renderScale = renderScale;
}
UpdateWaterProperties(m_reflectionCamera);
UpdateCameraProperties(camera, m_reflectionCamera);
UpdatePerspective(camera, m_reflectionCamera);
bool fogEnabled = RenderSettings.fog && !enableFog;
//Fog is based on clip-space z-distance and doesn't work with oblique projections
if (fogEnabled) SetFogState(false);
int maxLODLevel = QualitySettings.maximumLODLevel;
QualitySettings.maximumLODLevel = maximumLODLevel;
GL.invertCulling = true;
RenderReflection(context, m_reflectionCamera);
if (fogEnabled) SetFogState(true);
QualitySettings.maximumLODLevel = maxLODLevel;
GL.invertCulling = false;
UnityEngine.Profiling.Profiler.EndSample();
}
private void RenderReflection(ScriptableRenderContext context, Camera target)
{
/* Uncomment to render NR's vegetation in the reflection
// Register the reflection camera for Nature Renderer
var cameraId = VisualDesignCafe.Rendering.Instancing.RendererPool.RegisterCamera(target);
// Render the instanced objects (details and trees)
VisualDesignCafe.Rendering.Instancing.RendererPool.GetCamera(cameraId).Render();
*/
requestData = new UniversalRenderPipeline.SingleCameraRequest
{
destination = target.targetTexture,
slice = -1
};
if (RenderPipeline.SupportsRenderRequest(target, requestData))
{
RenderPipeline.SubmitRenderRequest(target, requestData);
}
}
private void SetFogState(bool value)
{
#if UNITY_EDITOR
UnityEditor.Unsupported.SetRenderSettingsUseFogNoDirty(value);
#else
RenderSettings.fog = value;
#endif
}
private float GetRenderScale()
{
return Mathf.Clamp(renderScale * UniversalRenderPipeline.asset.renderScale, 0.25f, 1f);
}
/// <summary>
/// Should the renderer index be changed at runtime, this function must be called to update any reflection cameras
/// </summary>
/// <param name="index"></param>
public void SetRendererIndex(int index)
{
index = PipelineUtilities.ValidateRenderer(index);
foreach (var kvp in reflectionCameras)
{
if (kvp.Value == null) continue;
m_cameraData = kvp.Value.GetComponent<UniversalAdditionalCameraData>();
m_cameraData.SetRenderer(index);
}
}
public void ToggleShadows(bool state)
{
foreach (var kvp in reflectionCameras)
{
if (kvp.Value == null) continue;
m_cameraData = kvp.Value.GetComponent<UniversalAdditionalCameraData>();
m_cameraData.renderShadows = state;
}
}
/// <summary>
/// Add the WaterObject, and recalculates the rendering bounds.
/// </summary>
/// <param name="waterObject"></param>
public void AddWaterObject(WaterObject waterObject)
{
ToggleMaterialReflectionSampling(waterObject, true);
waterObjects.Add(waterObject);
RecalculateBounds();
}
/// <summary>
/// Remove the WaterObject, and recalculates the rendering bounds.
/// </summary>
/// <param name="waterObject"></param>
public void RemoveWaterObject(WaterObject waterObject)
{
ToggleMaterialReflectionSampling(waterObject, false);
waterObjects.Remove(waterObject);
RecalculateBounds();
}
/// <summary>
/// Enables planar reflections on the MeshRenderers of the assigned water objects
/// </summary>
public void EnableMaterialReflectionSampling()
{
ToggleMaterialReflectionSampling(AllowReflections);
}
/// <summary>
/// Toggles the sampling of the planar reflections texture in the water shader.
/// </summary>
/// <param name="state"></param>
public void ToggleMaterialReflectionSampling(bool state)
{
if (waterObjects == null) return;
for (int i = 0; i < waterObjects.Count; i++)
{
if (waterObjects[i] == null) continue;
ToggleMaterialReflectionSampling(waterObjects[i], state);
}
}
private void ToggleMaterialReflectionSampling(WaterObject waterObject, bool state)
{
waterObject.props.SetFloat(_PlanarReflectionsEnabledID, state ? 1f : 0f);
waterObject.ApplyInstancedProperties();
}
private void CreateReflectionCamera(Camera source)
{
//Object creation
GameObject go = new GameObject($"{source.name} Planar Reflection");
go.hideFlags = HideFlags.DontSave | HideFlags.HideInHierarchy;
Camera newCamera = go.AddComponent<Camera>();
newCamera.hideFlags = HideFlags.DontSave;
//For the scene-view camera this also copies unwanted properties. Such as the camera type and background color!
newCamera.CopyFrom(source);
//Always exclude water layer
newCamera.cullingMask = ~(1 << 4) & cullingMask;
//Must always be set to Game, otherwise shadows render anyway
newCamera.cameraType = CameraType.Game;
newCamera.depth = source.depth-1f;
newCamera.rect = new Rect(0,0,1,1);
newCamera.enabled = false;
newCamera.clearFlags = includeSkybox ? CameraClearFlags.Skybox : CameraClearFlags.Depth;
//Required to maintain the alpha channel for the scene view
newCamera.backgroundColor = Color.clear;
//Occlusion culling has to be disabled, otherwise objects culled by the main camera will be culled for the reflection camera
//Setting the culling matrix for the camera doesn't appear to have any effect
newCamera.useOcclusionCulling = false;
//Component required for the UniversalRenderPipeline.RenderSingleCamera call
if (newCamera.gameObject.TryGetComponent<UniversalAdditionalCameraData>(out var data) == false)
{
data = newCamera.gameObject.AddComponent<UniversalAdditionalCameraData>();
}
data.requiresDepthTexture = false;
data.requiresColorTexture = false;
data.renderShadows = renderShadows;
rendererIndex = PipelineUtilities.ValidateRenderer(rendererIndex);
data.SetRenderer(rendererIndex);
CreateRenderTexture(newCamera, source);
reflectionCameras[source] = newCamera;
}
private void CreateRenderTexture(Camera targetCamera, Camera source)
{
//Note: Do not use RenderTextureFormat.Default or HDR, as these may be without an alpha channel on some platforms
RenderTextureFormat colorFormat = UniversalRenderPipeline.asset.supportsHDR && SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.ARGBHalf) ? RenderTextureFormat.ARGBHalf : RenderTextureFormat.ARGB32;
float scale = GetRenderScale();
RenderTextureDescriptor rtDsc = new RenderTextureDescriptor(
(int)((float)source.scaledPixelWidth * scale),
(int)((float)source.scaledPixelHeight * scale),
colorFormat);
rtDsc.depthBufferBits = 16;
//rtDsc.msaaSamples = UniversalRenderPipeline.asset.msaaSampleCount; //Waste of resources, water distortion makes it virtually unnoticeable.
targetCamera.targetTexture = RenderTexture.GetTemporary(rtDsc);
targetCamera.targetTexture.filterMode = scale < 1f ? FilterMode.Bilinear : FilterMode.Point;
targetCamera.targetTexture.name = $"{source.name}_Reflection {rtDsc.width}x{rtDsc.height}";
}
private static readonly Plane[] frustrumPlanes = new Plane[6];
public bool WaterObjectsVisible(Camera targetCamera)
{
GeometryUtility.CalculateFrustumPlanes(targetCamera.projectionMatrix * targetCamera.worldToCameraMatrix, frustrumPlanes);
return GeometryUtility.TestPlanesAABB(frustrumPlanes, bounds);
}
//Assigns the render target of the current reflection camera
private void UpdateWaterProperties(Camera cam)
{
for (int i = 0; i < waterObjects.Count; i++)
{
if (waterObjects[i] == null) continue;
waterObjects[i].props.SetFloat(_PlanarReflectionsEnabledID, 1);
waterObjects[i].props.SetTexture(_PlanarReflectionID, cam.targetTexture);
waterObjects[i].ApplyInstancedProperties();
}
}
private static Vector4 reflectionPlane;
private static Matrix4x4 reflectionBase;
private static Vector3 oldCamPos;
private static Matrix4x4 worldToCamera;
private static Matrix4x4 viewMatrix;
private static Matrix4x4 projectionMatrix;
private static Vector4 clipPlane;
private static readonly float[] layerCullDistances = new float[32];
private void UpdateCameraProperties(Camera source, Camera reflectionCam)
{
reflectionCam.fieldOfView = source.fieldOfView;
reflectionCam.orthographic = source.orthographic;
reflectionCam.orthographicSize = source.orthographicSize;
}
private void UpdatePerspective(Camera source, Camera reflectionCam)
{
if (!source || !reflectionCam) return;
Vector3 normal = rotatable ? this.transform.up : Vector3.up;
isUnderwater = (source.transform.position.y < bounds.center.y);
if (isUnderwater) normal = -Vector3.up;
Vector3 position = bounds.center + (normal * offset);
var d = -Vector3.Dot(normal, position);
reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d);
reflectionBase = Matrix4x4.identity;
reflectionBase *= Matrix4x4.Scale(new Vector3(1, -1, 1));
// View
CalculateReflectionMatrix(ref reflectionBase, reflectionPlane);
oldCamPos = source.transform.position - new Vector3(0, position.y * 2, 0);
reflectionCam.transform.forward = Vector3.Scale(source.transform.forward, new Vector3(1, -1, 1));
worldToCamera = source.worldToCameraMatrix;
viewMatrix = worldToCamera * reflectionBase;
//Reflect position
oldCamPos.y = -oldCamPos.y;
reflectionCam.transform.position = oldCamPos;
clipPlane = CameraSpacePlane(reflectionCam.worldToCameraMatrix, position - normal * 0.1f, normal, 1.0f);
projectionMatrix = source.CalculateObliqueMatrix(clipPlane);
//Settings
reflectionCam.cullingMask = ~(1 << 4) & cullingMask;;
m_reflectionCamera.clearFlags = includeSkybox ? CameraClearFlags.Skybox : CameraClearFlags.Depth;
reflectionCam.projectionMatrix = projectionMatrix;
reflectionCam.worldToCameraMatrix = viewMatrix;
//Unfortunately has to effect, camera appears ti use the culling matrix from the source camera anyway
reflectionCam.cullingMatrix = projectionMatrix * viewMatrix;
}
// Calculates reflection matrix around the given plane
private void CalculateReflectionMatrix(ref Matrix4x4 reflectionMat, Vector4 plane)
{
reflectionMat.m00 = (1F - 2F * plane[0] * plane[0]);
reflectionMat.m01 = (-2F * plane[0] * plane[1]);
reflectionMat.m02 = (-2F * plane[0] * plane[2]);
reflectionMat.m03 = (-2F * plane[3] * plane[0]);
reflectionMat.m10 = (-2F * plane[1] * plane[0]);
reflectionMat.m11 = (1F - 2F * plane[1] * plane[1]);
reflectionMat.m12 = (-2F * plane[1] * plane[2]);
reflectionMat.m13 = (-2F * plane[3] * plane[1]);
reflectionMat.m20 = (-2F * plane[2] * plane[0]);
reflectionMat.m21 = (-2F * plane[2] * plane[1]);
reflectionMat.m22 = (1F - 2F * plane[2] * plane[2]);
reflectionMat.m23 = (-2F * plane[3] * plane[2]);
reflectionMat.m30 = 0F;
reflectionMat.m31 = 0F;
reflectionMat.m32 = 0F;
reflectionMat.m33 = 1F;
}
// Given position/normal of the plane, calculates plane in camera space.
private Vector4 CameraSpacePlane(Matrix4x4 worldToCameraMatrix, Vector3 pos, Vector3 normal, float sideSign)
{
var offsetPos = pos + normal * offset;
var cameraPosition = worldToCameraMatrix.MultiplyPoint(offsetPos);
var cameraNormal = worldToCameraMatrix.MultiplyVector(normal).normalized * sideSign;
return new Vector4(cameraNormal.x, cameraNormal.y, cameraNormal.z,
-Vector3.Dot(cameraPosition, cameraNormal));
}
public RenderTexture TryGetReflectionTexture(Camera targetCamera)
{
if (targetCamera)
{
reflectionCameras.TryGetValue(targetCamera, out m_reflectionCamera);
if (m_reflectionCamera)
{
return m_reflectionCamera.targetTexture;
}
}
return null;
}
#endif
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c1b629e2b9e73f34a859a756e1560ad1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: -1426863774865177168, guid: 0000000000000000d000000000000000, type: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 287769
packageName: Stylized Water 3
packageVersion: 3.2.6
assetPath: Assets/Stylized Water 3/Runtime/Rendering/PlanarReflectionRenderer.cs
uploadId: 895866
@@ -0,0 +1,139 @@
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace StylizedWater3
{
/// <summary>
/// Utility for creating an orthographic top-down projection
/// </summary>
public class PlanarProjection
{
private static readonly Quaternion viewRotation = Quaternion.Euler(new Vector3(90f, 0f, 0f));
private static readonly Vector3 viewScale = new Vector3(1, 1, -1);
private static readonly Plane[] frustrumPlanes = new Plane[6];
//Input
public Vector3 center;
public Vector3 offset;
public float scale;
public int resolution;
public bool expandHeight = true;
//Output
public Matrix4x4 projection;
public Matrix4x4 view;
public Rect viewportRect;
public Vector3 boundsMin;
public Vector3 boundsMax;
//Important to snap the projection to the nearest texel. Otherwise pixel swimming is introduced when moving, due to bilinear filtering
private static Vector3 Stabilize(Vector3 pos, float texelSize)
{
float Snap(float coord, float cellSize) => Mathf.FloorToInt(coord / cellSize) * (cellSize) + (cellSize * 0.5f);
return new Vector3(Snap(pos.x, texelSize), Snap(pos.y, texelSize), Snap(pos.z, texelSize));
}
public void Recalculate()
{
float extent = scale * 0.5f;
Vector3 centerPosition = center + offset;
//var frustumHeight = 2.0f * scale * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad); //Still clips, plus doesn't support orthographc
var frustumHeight = expandHeight ? 10000f : scale;
centerPosition += (Vector3.up * frustumHeight * 0.5f);
centerPosition = Stabilize(centerPosition, scale / resolution);
projection = Matrix4x4.Ortho(-extent, extent, -extent, extent, 0.02f, frustumHeight);
view = Matrix4x4.TRS(centerPosition, viewRotation, viewScale).inverse;
viewportRect = new Rect(0, 0, resolution, resolution);
boundsMin.x = centerPosition.x - extent;
boundsMin.y = centerPosition.y - extent;
boundsMin.z = centerPosition.z - extent;
boundsMax.x = centerPosition.z + extent;
boundsMax.y = centerPosition.z + extent;
boundsMax.z = centerPosition.z + extent;
}
/// <summary>
/// Sets a Vector4 uniform up to be passed onto shader land, where a world-space position can be used to calculate a sampling UV
/// </summary>
/// <param name="coords"></param>
public void SetUV(ref Vector4 coords)
{
coords.x = boundsMin.x;
coords.y = boundsMin.z;
coords.z = scale;
coords.w = 1; //Enable sampling shaders
}
public void SetProjection(RasterCommandBuffer cmd)
{
cmd.SetViewProjectionMatrices(view, projection);
//Unity 6000.0.30f1+ only
//RenderingUtils.SetViewAndProjectionMatrices(cmd, view, projection, true);
}
public static int CalculateResolution(float scale, int texelsPerUnit, int min, int max)
{
int res = Mathf.RoundToInt(scale * texelsPerUnit);
//if(NON_POWER_OF_TWO == false) res = Mathf.NextPowerOfTwo(res);
return Mathf.Clamp(res, min, max);
}
public static float FadePercentageToLength(float renderRange, float fadePercentage)
{
fadePercentage = Mathf.Max(0.01f, fadePercentage);
return (renderRange * 0.5f) * (fadePercentage / 100f);
}
public void CalculateFrustumPlanes()
{
GeometryUtility.CalculateFrustumPlanes(projection * view, frustrumPlanes);
}
public bool TestPlanesAABB(Bounds bounds)
{
return GeometryUtility.TestPlanesAABB(frustrumPlanes, bounds);
}
//Using data only from the matrices, to ensure what you're seeing closely represents them
public void DrawOrthographicViewGizmo()
{
Gizmos.matrix = Matrix4x4.identity;
CalculateFrustumPlanes();
float near = frustrumPlanes[4].distance;
float far = frustrumPlanes[5].distance;
float height = near + far;
Vector3 position = new Vector3(view.inverse.m03, view.inverse.m13, view.inverse.m23);
Vector3 orthoSize = new Vector3((frustrumPlanes[0].distance + frustrumPlanes[1].distance), height, frustrumPlanes[2].distance + frustrumPlanes[3].distance);
//orthoSize = Vector3.one * 50f;
Gizmos.DrawSphere(position, 1f);
position -= Vector3.up * height * 0.5f;
Gizmos.DrawWireCube(position, orthoSize);
Gizmos.color = Color.white * 0.25f;
Gizmos.DrawCube(position, orthoSize);
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5e9fd4f2cdd74b138fb2b5f8ba29094c
timeCreated: 1717679203
AssetOrigin:
serializedVersion: 1
productId: 287769
packageName: Stylized Water 3
packageVersion: 3.2.6
assetPath: Assets/Stylized Water 3/Runtime/Rendering/ProjectionUtils.cs
uploadId: 895866
@@ -0,0 +1,149 @@
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
using UnityEngine;
using UnityEngine.Rendering;
#if URP
using UnityEngine.Rendering.Universal;
using UnityEngine.Rendering.Universal.Internal;
using UnityEngine.Rendering.RenderGraphModule;
namespace StylizedWater3
{
public class SetupConstants : ScriptableRenderPass
{
private ProfilingSampler m_ProfilingSampler;
private static readonly int _CausticsProjectionAvailable = Shader.PropertyToID("_CausticsProjectionAvailable");
private static readonly int CausticsProjection = Shader.PropertyToID("CausticsProjection");
private static readonly int _WaterSSRParams = Shader.PropertyToID("_WaterSSRParams");
private static readonly int _WaterSSRSettings = Shader.PropertyToID("_WaterSSRSettings");
private static VisibleLight mainLight;
private Matrix4x4 causticsProjection;
public SetupConstants()
{
//Force a unit scale, otherwise affects the projection tiling of the caustics
causticsProjection = Matrix4x4.Scale(Vector3.one);
}
private StylizedWaterRenderFeature settings;
public void Setup(StylizedWaterRenderFeature renderFeature)
{
this.settings = renderFeature;
/*
//Whilst required for these features, do not impose onto the render pipeline
//User must manage the enabled state of depth texture
if (settings.screenSpaceReflectionSettings.allow || settings.allowDirectionalCaustics)
{
ConfigureInput(ScriptableRenderPassInput.Depth);
}
*/
}
private class PassData
{
public UniversalCameraData cameraData;
public bool directionalCaustics;
public Matrix4x4 causticsProjection;
public bool ssr;
public bool ssrSkybox;
}
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
UniversalLightData lightData = frameData.Get<UniversalLightData>();
UniversalCameraData cameraData = frameData.Get<UniversalCameraData>();
#if UNITY_EDITOR || DEVELOPMENT_BUILD
frameData.GetOrCreate<StylizedWaterRenderFeature.DebugData>();
#endif
using (var builder = renderGraph.AddRasterRenderPass<PassData>("Water Constants", out var passData, m_ProfilingSampler))
{
passData.ssr = settings.screenSpaceReflectionSettings.allow;
passData.ssrSkybox = settings.screenSpaceReflectionSettings.reflectEverything;
passData.directionalCaustics = settings.allowDirectionalCaustics;
if (passData.directionalCaustics)
{
//When no lights are visible, main light will be set to -1.
if (lightData.mainLightIndex > -1)
{
mainLight = lightData.visibleLights[lightData.mainLightIndex];
if (mainLight.lightType == LightType.Directional)
{
causticsProjection = Matrix4x4.Rotate(mainLight.light.transform.rotation);
passData.causticsProjection = causticsProjection.inverse;
passData.cameraData = cameraData;
}
else
{
passData.directionalCaustics = false;
}
}
else
{
passData.directionalCaustics = false;
}
}
//Pass should always execute
builder.AllowPassCulling(false);
builder.AllowGlobalStateModification(true);
builder.SetRenderFunc((PassData data, RasterGraphContext rgContext) =>
{
Execute(rgContext.cmd, data);
});
}
}
static void Execute(RasterCommandBuffer cmd, PassData data)
{
cmd.SetGlobalVector(_WaterSSRParams, new Vector4(data.ssr ? 1 : 0, data.ssrSkybox ? 1 : 0, 0));
//Exposed settings not ready yet, would like to refactor the raymarching to use a step-distance, rather than a fixed number of steps.
cmd.SetGlobalVector(_WaterSSRSettings, new Vector4(12, 0.75f, 100f, 1.0f));
cmd.SetGlobalInt(_CausticsProjectionAvailable, data.directionalCaustics ? 1 : 0);
if (data.directionalCaustics)
{
cmd.SetGlobalMatrix(CausticsProjection, data.causticsProjection);
//Sets up the required View- -> Clip-space matrices
NormalReconstruction.SetupProperties(cmd, data.cameraData);
}
}
public override void OnCameraCleanup(CommandBuffer cmd)
{
//Important to disable these features, as the next camera rendering may be using a different renderer altogether
cmd.SetGlobalInt(_CausticsProjectionAvailable, 0);
cmd.SetGlobalVector(_WaterSSRParams, Vector4.zero);
}
public void Dispose()
{
}
#if !UNITY_6000_4_OR_NEWER
#pragma warning disable CS0672
#pragma warning disable CS0618
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { }
#pragma warning restore CS0672
#pragma warning restore CS0618
#endif
}
}
#endif
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 68f653ef6f17f454595b16a58a2cdbfd
timeCreated: 1701078225
AssetOrigin:
serializedVersion: 1
productId: 287769
packageName: Stylized Water 3
packageVersion: 3.2.6
assetPath: Assets/Stylized Water 3/Runtime/Rendering/SetupConstants.cs
uploadId: 895866
@@ -0,0 +1,385 @@
// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
// • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
// • Uploading this file to a public repository will subject it to an automated DMCA takedown request.
#if UNITY_EDITOR || DEVELOPMENT_BUILD
#define DEBUG_AVAILABLE
#endif
#if URP
using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.RenderGraphModule;
using UnityEngine.Rendering.RenderGraphModule.Util;
using UnityEngine.Rendering.Universal;
using UnityEngine.Serialization;
namespace StylizedWater3
{
[DisallowMultipleRendererFeature("Stylized Water 3")]
public partial class StylizedWaterRenderFeature : ScriptableRendererFeature
{
[Tooltip("Render all transparent materials NOT on the \"Water\" layer into a screen-space texture, and use that for refraction rendering in the water." +
"\n\n" +
"If enabled, transparent materials can be submerged and refracted correctly")]
public bool transparencyRefraction;
public static StylizedWaterRenderFeature GetDefault()
{
return (StylizedWaterRenderFeature)PipelineUtilities.GetRenderFeature<StylizedWaterRenderFeature>();
}
[Serializable]
public class ScreenSpaceReflectionSettings
{
[FormerlySerializedAs("enable")]
[Tooltip("Allow SSR to be rendered in water materials that have it enabled." +
"\n\nDisable as a global performance scaling measure")]
public bool allow = true;
[FormerlySerializedAs("reflectSkybox")]
[Tooltip("Only enable when Reflection Probes cannot be used in a realtime lighting setup. If enabled, SSR will also reflects the skybox color and geometry in front of the water." +
"\n\nIdeally disabled, so that Reflection Probes can be relied on for a 1:1 accurate skybox reflection.")]
public bool reflectEverything = false;
}
public ScreenSpaceReflectionSettings screenSpaceReflectionSettings = new ScreenSpaceReflectionSettings();
[FormerlySerializedAs("directionalCaustics")]
[Tooltip("Pass on the main directional light's projection onto the water shader. Allows caustics to project along its direction (rather than top-down)." +
"\n\nThis shading operation is relative expensive, as it involves analyzing the depth texture at 4 different points")]
public bool allowDirectionalCaustics;
public HeightPrePass.Settings heightPrePassSettings = new HeightPrePass.Settings();
#if SWS_DEV
public TerrainHeightPrePass.Settings terrainHeightPrePassSettings = new TerrainHeightPrePass.Settings();
#endif
private SetupConstants constantsSetup;
private HeightPrePass heightPrePass;
private HeightQuerySystem.RenderPass heightQueryPass;
#if SWS_DEV
private TerrainHeightPrePass terrainHeightPrePass;
private DistanceFieldPass distanceFieldPass;
private RenderTransparentTexture transparentTexturePass;
#endif
#if DEBUG_AVAILABLE
private DebugInspectorPass debugInspectorPass;
#endif
[SerializeField]
public ComputeShader heightReadbackCS;
[SerializeField]
public Shader heightProcessingShader;
/// <summary>
/// Set this to true from a render pass if it requires the displacement pre-pass, despite it being disabled in the render feature settings.
/// </summary>
public static bool RequireHeightPrePass;
protected bool WillExecuteHeightPrePass => RequireHeightPrePass || heightPrePassSettings.enable || HeightQuerySystem.RequiresHeightPrepass;
private void OnValidate()
{
VerifyReferences();
}
private void Reset()
{
VerifyReferences();
}
public void VerifyReferences()
{
if (!heightReadbackCS)
{
#if UNITY_EDITOR
//HeightSampler.cs
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath("768e0c28dfdbc6b429fd59518fa03f2d");
ComputeShader cs = UnityEditor.AssetDatabase.LoadAssetAtPath<ComputeShader>(assetPath);
if (cs)
{
heightReadbackCS = cs;
}
#endif
}
if(!heightProcessingShader) heightProcessingShader = Shader.Find(ShaderParams.ShaderNames.HeightProcessor);
#if SWS_DEV
if(!terrainHeightPrePassSettings.terrainHeightVisualizationShader) terrainHeightPrePassSettings.terrainHeightVisualizationShader = Shader.Find(ShaderParams.ShaderNames.TerrainHeight);
#endif
VerifyUnderwaterRendering();
}
public class DebugData : ContextItem
{
public TextureHandle currentHandle;
public override void Reset()
{
currentHandle = TextureHandle.nullHandle;
}
}
public override void Create()
{
GraphicsDeviceType currentGraphicsAPI = SystemInfo.graphicsDeviceType;
//https://issuetracker.unity3d.com/issues/crash-on-gfxdeviced3d12base-drawbufferscommon-when-adding-specific-custom-render-pass-feature-to-renderer
//Now fixed in Unity 6000.0.60f1
#if !UNITY_6000_1_OR_NEWER
if (currentGraphicsAPI == GraphicsDeviceType.Direct3D12 || currentGraphicsAPI == GraphicsDeviceType.XboxOneD3D12)
{
//Using the "BeforeRendering" point causes a fatal crash when using DX12 when allocating a RT
//defaultInjectionPoint = RenderPassEvent.BeforeRenderingShadows;
}
#endif
constantsSetup = new SetupConstants
{
renderPassEvent = defaultInjectionPoint
};
heightPrePass = new HeightPrePass
{
renderPassEvent = defaultInjectionPoint
};
heightQueryPass = new HeightQuerySystem.RenderPass()
{
renderPassEvent = defaultInjectionPoint
};
#if SWS_DEV
terrainHeightPrePass = new TerrainHeightPrePass()
{
renderPassEvent = defaultInjectionPoint
};
if (transparencyRefraction)
{
transparentTexturePass = new RenderTransparentTexture();
transparentTexturePass.renderPassEvent = RenderPassEvent.BeforeRenderingTransparents;
}
#endif
CreateFlowMapPass();
CreateDynamicEffectsPasses();
CreateUnderwaterRenderingPasses();
#if DEBUG_AVAILABLE
debugInspectorPass = new DebugInspectorPass();
debugInspectorPass.renderPassEvent = RenderPassEvent.AfterRendering;
#endif
}
//Note: Actually prefer to render before transparents, but this creates a recursive RenderSingleCamera call
//Restoring the view/projection to that of the camera also breaks VR. Required functions are internal URP code
//In some cases, if no pre-passes render (depth, shadows, etc) then the projection does not get reset when rendering the opaque objects pass. Hence, things must render as early as possible.
private static RenderPassEvent defaultInjectionPoint = RenderPassEvent.BeforeRendering;
//Dynamic Effects
partial void CreateDynamicEffectsPasses();
partial void AddDynamicEffectsPasses(ScriptableRenderer renderer, ref RenderingData renderingData);
partial void DisposeDynamicEffectsPasses();
partial void VerifyUnderwaterRendering();
partial void CreateUnderwaterRenderingPasses();
partial void AddUnderwaterRenderingPasses(ScriptableRenderer renderer, ref RenderingData renderingData);
partial void DisposeUnderwaterRenderingPasses();
partial void CreateFlowMapPass();
partial void AddFlowMapPass(ScriptableRenderer renderer, ref RenderingData renderingData);
partial void DisposeFlowMapPass();
private bool IsInvalidContext(CameraType cameraType, CameraRenderType cameraRenderType)
{
//Skip for any special use camera's (except scene view camera)
if (cameraType != CameraType.SceneView && (cameraType == CameraType.Preview || hideFlags != HideFlags.None))
{
return true;
}
//Skip overlay cameras
if (cameraRenderType == CameraRenderType.Overlay)
{
return true;
}
return false;
}
private bool isMainCamera(Camera camera)
{
//Skip for any special use camera's (except scene view camera)
return (camera.cameraType == CameraType.SceneView || camera.CompareTag("MainCamera"));
}
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
{
var currentCam = renderingData.cameraData.camera;
if(IsInvalidContext(currentCam.cameraType, renderingData.cameraData.renderType)) return;
constantsSetup.Setup(this);
renderer.EnqueuePass(constantsSetup);
#if SWS_DEV
if (terrainHeightPrePassSettings.enable)
{
terrainHeightPrePass.Setup(terrainHeightPrePassSettings);
renderer.EnqueuePass(terrainHeightPrePass);
}
if (transparencyRefraction)
{
renderer.EnqueuePass(transparentTexturePass);
}
#endif
//Do not execute for reflection probe captures
if (currentCam.cameraType != CameraType.Reflection)
{
AddFlowMapPass(renderer, ref renderingData);
AddDynamicEffectsPasses(renderer, ref renderingData);
//Do not execute for the scene-view camera in play-mode. Even if the tab is not active, it would render around it instead of the main camera
var skipHeightPrePass = Application.isPlaying && heightPrePassSettings.disableInSceneView && currentCam.cameraType == CameraType.SceneView;
//In play-mode, strictly execute for the main camera
skipHeightPrePass |= Application.isPlaying && !currentCam.CompareTag("MainCamera");
if (WillExecuteHeightPrePass && skipHeightPrePass == false)
{
//Debug.Log($"Executing height pre-pass for {currentCam.name}");
heightPrePass.Setup(heightPrePassSettings);
renderer.EnqueuePass(heightPrePass);
if (HeightQuerySystem.QueryCount > 0)
{
heightQueryPass.Setup(this, heightReadbackCS);
renderer.EnqueuePass(heightQueryPass);
}
}
else
{
Shader.SetGlobalInt(HeightPrePass._WaterHeightPrePassAvailable, 0);
}
}
AddUnderwaterRenderingPasses(renderer, ref renderingData);
#if DEBUG_AVAILABLE
if (RenderTargetDebugger.InspectedProperty > 0)
{
renderer.EnqueuePass(debugInspectorPass);
}
#endif
}
protected override void Dispose(bool disposing)
{
constantsSetup.Dispose();
heightPrePass.Dispose();
heightQueryPass.Dispose();
#if SWS_DEV
terrainHeightPrePass.Dispose();
#endif
DisposeFlowMapPass();
DisposeDynamicEffectsPasses();
DisposeUnderwaterRenderingPasses();
}
#if DEBUG_AVAILABLE
private class DebugInspectorPass : ScriptableRenderPass
{
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData)
{
DebugData debugData = frameData.Get<DebugData>();
//Whichever pass's render target PropertyID matches the selected one in the inspector window get assigned as the 'currentHandle'
if (debugData.currentHandle.IsValid())
{
var destinationDesc = renderGraph.GetTextureDesc(debugData.currentHandle);
destinationDesc.clearBuffer = false;
RenderTextureDescriptor rtDsc = new RenderTextureDescriptor
{
width = destinationDesc.width,
height = destinationDesc.height,
//If you're seeing an error here you are not using a compatible Unity version!
graphicsFormat = destinationDesc.colorFormat,
#if UNITY_6000_1_OR_NEWER
colorFormat = RenderTextureFormat.Default,
#endif
volumeDepth = 1,
dimension = destinationDesc.dimension,
useMipMap = destinationDesc.useMipMap,
msaaSamples = 1
};
TextureDesc textureDesc = debugData.currentHandle.GetDescriptor(renderGraph);
var allocate = RenderTargetDebugger.CurrentRT == null || RenderTargetDebugger.CurrentRT.rt == null;
if (allocate == false)
{
allocate |= RenderTargetDebugger.CurrentRT.rt.name != textureDesc.name;
//RTMF :') Update to a supported Unity 6.0 version if this throws an error
allocate |= RenderTargetDebugger.CurrentRT.rt.graphicsFormat != textureDesc.format;
allocate |= RenderTargetDebugger.CurrentRT.rt.width != textureDesc.width;
allocate |= RenderTargetDebugger.CurrentRT.rt.height != textureDesc.height;
}
if (allocate)
{
textureDesc.name += " (Debug)";
//Debug.Log($"Reallocating debug RT ({textureDesc.name})");
RenderTargetDebugger.CurrentRT?.Release();
RenderTargetDebugger.CurrentRT = RTHandles.Alloc(rtDsc, name: textureDesc.name);
}
//Idiotic function keeps causing memory leaks since Unity 2021
//RenderingUtils.ReAllocateHandleIfNeeded(ref RenderTargetDebugger.CurrentRT, rtDsc, textureDesc.filterMode, textureDesc.wrapMode, textureDesc.anisoLevel, textureDesc.mipMapBias, textureDesc.name);
TextureHandle destination = renderGraph.ImportTexture(RenderTargetDebugger.CurrentRT);
if (destination.IsValid() == false)
{
throw new Exception("Failed to generate debugger texture");
}
else
{
var cameraData = frameData.Get<UniversalCameraData>();
RenderTargetDebugger.CurrentCameraName = cameraData.camera.name;
//Copy TextureHandle into persistent RT
renderGraph.AddCopyPass(debugData.currentHandle, destination, passName: "Water Debug");
}
}
else
{
RenderTargetDebugger.CurrentRT = null;
RenderTargetDebugger.CurrentCameraName = string.Empty;
}
}
#if !UNITY_6000_4_OR_NEWER
#pragma warning disable CS0672
#pragma warning disable CS0618
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { }
#pragma warning restore CS0672
#pragma warning restore CS0618
#endif
}
#endif //DEBUG_AVAILABLE
}
}
#endif
@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: 1c6e585d9d2317e438a403bbb1965d5e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- heightReadbackCS: {fileID: 7200000, guid: 768e0c28dfdbc6b429fd59518fa03f2d, type: 3}
- heightProcessingShader: {fileID: 4800000, guid: a1cfcf2c2c8140c084fb10845093540e,
type: 3}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 287769
packageName: Stylized Water 3
packageVersion: 3.2.6
assetPath: Assets/Stylized Water 3/Runtime/Rendering/StylizedWaterRenderFeature.cs
uploadId: 895866