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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEditor; using UnityEditor;
using UnityEngine; using UnityEngine;
using UnityEngine.Rendering; using UnityEngine.Rendering;
@ -8,24 +9,36 @@ using UnityEngine.XR;
public class DepthRenderPassFeature : ScriptableRendererFeature 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 Task<float[]> RequestDepthDataAsync(int id)
public static Queue<bool> Requests; {
public static Queue<float[]> Answers; 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"); ProfilingSampler m_ProfilingSampler = new ProfilingSampler("ColorBlit");
private Material material; private Material material;
private RTHandle rtHandle; private RTHandle rtHandle;
private RTHandle copyRtHandle;
private bool depth = false; private bool depth = false;
private ComputeBuffer computeBuffer; private ComputeBuffer computeBuffer;
public DepthRenderPass(Material material) public DepthRenderPass(Material material)
{ {
this.material = material; this.material = material;
Requests = new Queue<bool>();
Answers = new Queue<float[]>();
} }
public void SetTarget(RTHandle handle, bool depth) public void SetTarget(RTHandle handle, bool depth)
@ -48,6 +61,8 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData) public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
{ {
ConfigureTarget(rtHandle); ConfigureTarget(rtHandle);
var desc = renderingData.cameraData.cameraTargetDescriptor;
RenderingUtils.ReAllocateIfNeeded(ref copyRtHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp);
} }
// Here you can implement the rendering logic. // Here you can implement the rendering logic.
@ -57,22 +72,31 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{ {
CommandBuffer cmd = CommandBufferPool.Get(); CommandBuffer cmd = CommandBufferPool.Get();
//RTHandle rt = renderingData.cameraData.renderer.cameraColorTargetHandle;
using (new ProfilingScope(cmd, m_ProfilingSampler)) using (new ProfilingScope(cmd, m_ProfilingSampler))
{ {
Blitter.BlitCameraTexture(cmd, rtHandle, rtHandle, material, 0); 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); context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(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. // Cleanup any allocated resources that were created during the execution of this render pass.
@ -100,18 +124,6 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
{ {
DestroyComputeBuffer(); DestroyComputeBuffer();
} }
if (Requests != null)
{
Requests.Clear();
Requests = null;
}
if (Answers != null)
{
Answers.Clear();
Answers = null;
}
} }
public void DestroyComputeBuffer() public void DestroyComputeBuffer()
@ -169,8 +181,16 @@ public class DepthRenderPassFeature : ScriptableRendererFeature
Destroy(material); Destroy(material);
#endif #endif
m_ScriptablePass.Dispose(); 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UnityEditor.Rendering; using UnityEditor.Rendering;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
@ -14,15 +16,20 @@ public class DepthTester : MonoBehaviour
private Camera camera; private Camera camera;
private float farPlane; private float farPlane;
private float nearPlane; private float nearPlane;
private int id;
private Task<float[]> task;
// Start is called before the first frame update // Start is called before the first frame update
void Start() void Start()
{ {
camera = GetComponent<Camera>(); camera = GetComponent<Camera>();
id = camera.GetInstanceID();
farPlane = camera.farClipPlane; farPlane = camera.farClipPlane;
nearPlane = camera.nearClipPlane; nearPlane = camera.nearClipPlane;
texture = BlendShaderController.CreateTextures(1, FrameRes, FrameRes, false)[0]; texture = BlendShaderController.CreateTextures(1, FrameRes, FrameRes, false)[0];
camera.targetTexture = texture; camera.targetTexture = texture;
texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false); texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBAFloat, false);
task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
} }
private void OnDisable() private void OnDisable()
@ -40,18 +47,29 @@ public class DepthTester : MonoBehaviour
private void Update() private void Update()
{ {
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; Vector3 depthPos = transform.position + transform.right * Offset;
RenderTexture.active = texture; Debug.DrawLine(depthPos, depthPos + transform.forward * depth, Color.green);
texture2D.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); Debug.Log($"chto to risuet: dist:{depth}; depthsCount: {depths.Length}");
texture2D.Apply(); task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
Color pixel = texture2D.GetPixel(texture.width / 2, texture2D.height / 2); }
float depth = pixel.r; else if(task.IsCanceled)
float depthDist = depth * farPlane; {
Debug.DrawLine(depthPos, depthPos + transform.forward * depthDist, Color.green); task = DepthRenderPassFeature.DepthRenderPass.RequestDepthDataAsync(id);
}
}
}
Vector3 raycastPos = transform.position - transform.right * Offset; Vector3 raycastPos = transform.position - transform.right * Offset;
float rayDistance = 0; float rayDistance = 0;
if(Physics.Raycast(transform.position, transform.forward, out var hit, 100)) if(Physics.Raycast(transform.position, transform.forward, out var hit, 100))
{ {
rayDistance = hit.distance; rayDistance = hit.distance;

View File

@ -26,7 +26,7 @@ Shader "Hidden/RenderDepth"
sampler2D _MainTex; sampler2D _MainTex;
RWStructuredBuffer<float> distBuffer; RWStructuredBuffer<float> distBuffer : register(u1);
int res; int res;
bool _RenderDepth; bool _RenderDepth;
@ -42,7 +42,7 @@ Shader "Hidden/RenderDepth"
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(i.texcoord)); real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(i.texcoord));
#endif #endif
depth = Linear01Depth(depth, _ZBufferParams); 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); return _RenderDepth ? float4(depth, depth, depth, 1) : float4(color, 1);
} }
ENDHLSL ENDHLSL