Added reading of depth independent of mode

- Added writing distances in buffer in RenderDepth.shader
 - Added reading distances directly from render pass in DepthRenderPassFeature.cs
 - Added example depth reading in DepthTester.cs
This commit is contained in:
Max Barashev 2026-06-03 21:48:43 +03:00
parent a2f9328f5f
commit 0749c2fbe7
3 changed files with 78 additions and 40 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
@ -8,24 +9,36 @@ using UnityEngine.XR;
public class DepthRenderPassFeature : ScriptableRendererFeature
{
class DepthRenderPass : ScriptableRenderPass
private static Dictionary<int, Queue<TaskCompletionSource<float[]>>> m_PendingRequests = new();
internal class DepthRenderPass : ScriptableRenderPass
{
public static Action<float[]> OnDepthReady;
public static Queue<bool> Requests;
public static Queue<float[]> Answers;
public static Task<float[]> RequestDepthDataAsync(int id)
{
if(m_PendingRequests == null)
m_PendingRequests = new Dictionary<int, Queue<TaskCompletionSource<float[]>>>();
var tcs = new TaskCompletionSource<float[]>();
int key = id;
if (!m_PendingRequests.TryGetValue(key, out var queue))
{
queue = new Queue<TaskCompletionSource<float[]>>();
m_PendingRequests.Add(key, queue);
}
queue.Enqueue(tcs);
return tcs.Task;
}
ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit");
private Material material;
private RTHandle rtHandle;
private RTHandle copyRtHandle;
private bool depth = false;
private ComputeBuffer computeBuffer;
public DepthRenderPass(Material material)
{
this.material = material;
Requests = new Queue<bool>();
Answers = new Queue<float[]>();
}
public void SetTarget(RTHandle handle, bool depth)
@ -48,6 +61,8 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{
ConfigureTarget(rtHandle);
var desc = renderingData.cameraData.cameraTargetDescriptor;
RenderingUtils.ReAllocateIfNeeded(ref copyRtHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp);
}
// Here you can implement the rendering logic.
@ -57,22 +72,31 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
CommandBuffer cmd = CommandBufferPool.Get();
//RTHandle rt = renderingData.cameraData.renderer.cameraColorTargetHandle;
using (new ProfilingScope(cmd, m_ProfilingSampler))
{
Blitter.BlitCameraTexture(cmd, rtHandle, rtHandle, material, 0);
if(Requests.Count > 0)
{
Requests.Dequeue();
float[] resultArray = new float[computeBuffer.count];
computeBuffer.GetData(resultArray);
Answers.Enqueue(resultArray);
}
}
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
lock(m_PendingRequests)
{
if (m_PendingRequests.Count > 0)
{
int key = renderingData.cameraData.camera.GetInstanceID();
if (m_PendingRequests.TryGetValue(key, out var queue) && queue.Count > 0)
{
float[] result = new float[computeBuffer.count];
material.SetBuffer("distBuffer", computeBuffer);
Graphics.SetRandomWriteTarget(1, computeBuffer,false);
computeBuffer.GetData(result);
while (queue.TryDequeue(out var tcs))
tcs.TrySetResult(result);
}
}
}
}
// Cleanup any allocated resources that were created during the execution of this render pass.
@ -100,18 +124,6 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
{
DestroyComputeBuffer();
}
if (Requests != null)
{
Requests.Clear();
Requests = null;
}
if (Answers != null)
{
Answers.Clear();
Answers = null;
}
}
public void DestroyComputeBuffer()
@ -169,8 +181,16 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
Destroy(material);
#endif
m_ScriptablePass.Dispose();
if (m_PendingRequests != null)
{
foreach (var queue in m_PendingRequests.Values)
{
while (queue.TryDequeue(out var tcs))
tcs.TrySetCanceled();
}
m_PendingRequests.Clear();
}
}
}

View File

@ -1,5 +1,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.UIElements;
@ -14,15 +16,20 @@ public class DepthTester : MonoBehaviour
private Camera camera;
private float farPlane;
private float nearPlane;
private int id;
private Task<float[]> task;
// Start is called before the first frame update
void Start()
{
camera = GetComponent<Camera>();
id = camera.GetInstanceID();
farPlane = camera.farClipPlane;
nearPlane = camera.nearClipPlane;
texture = BlendShaderController.CreateTextures(1, FrameRes, FrameRes, false)[0];
camera.targetTexture = texture;
texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false);
task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
}
private void OnDisable()
@ -40,18 +47,29 @@ public class DepthTester : MonoBehaviour
private void Update()
{
Vector3 depthPos = transform.position + transform.right * Offset;
RenderTexture.active = texture;
texture2D.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0);
texture2D.Apply();
Color pixel = texture2D.GetPixel(texture.width / 2, texture2D.height / 2);
float depth = pixel.r;
float depthDist = depth * farPlane;
Debug.DrawLine(depthPos, depthPos + transform.forward * depthDist, Color.green);
lock(task)
{
if(task != null)
{
if(task.IsCompletedSuccessfully)
{
float[] depths = task.Result;
int centerIndex = (FrameRes / 2) * FrameRes + (FrameRes / 2);
float depth = depths[centerIndex];
Vector3 depthPos = transform.position + transform.right * Offset;
Debug.DrawLine(depthPos, depthPos + transform.forward * depth, Color.green);
Debug.Log($"chto to risuet: dist:{depth}; depthsCount: {depths.Length}");
task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
}
else if(task.IsCanceled)
{
task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
}
}
}
Vector3 raycastPos = transform.position - transform.right * Offset;
float rayDistance = 0;
if(Physics.Raycast(transform.position, transform.forward, out var hit, 100))
{
rayDistance = hit.distance;

View File

@ -26,7 +26,7 @@ Shader "Hidden/RenderDepth"
sampler2D _MainTex;
RWStructuredBuffer<float> distBuffer;
RWStructuredBuffer<float> distBuffer : register(u1);
int res;
bool _RenderDepth;
@ -42,7 +42,7 @@ Shader "Hidden/RenderDepth"
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(i.texcoord));
#endif
depth = Linear01Depth(depth, _ZBufferParams);
distBuffer[pixelIdx.y * _ScaledScreenParams.x + pixelIdx.x] = depth * _ProjectionParams.z;
distBuffer[pixelIdx.y * (uint)_ScaledScreenParams.x + pixelIdx.x] = depth * _ProjectionParams.z;
return _RenderDepth ? float4(depth, depth, depth, 1) : float4(color, 1);
}
ENDHLSL