Last active
March 2, 2024 13:47
-
-
Save lachlansleight/1e02652bc5a298cba4004dca2a54942d to your computer and use it in GitHub Desktop.
Depth Camera Image to World-Space Position (Unity Compute Shader)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is the old version of my shader - I'm in London atm and don't have the new project that spawns particles to hand | |
// In this one, there's one particl | |
// The particles are something like | |
struct Particle { | |
int2 PixelPosition; | |
float3 WorldSpacePosition; | |
} | |
// compute buffer matched to the particle struct | |
RWStructuredBuffer<Particle> ParticleBuffer; | |
// R16 depth texture from RealSense - maybe this could be Texture2D<float> idk lol | |
Texture2D<float4> DepthTexture; | |
// transform.localToWorldMatrix of the transform I use to represent the depth camera in the scene | |
float4x4 TransformMatrix; | |
// size of the depth texture in pixels | |
float2 FrameSize; | |
// literally just FrameSize.x / FrameSize.y - precomputed when we send the texture pointer | |
float FrameRatio; | |
// matched to the number of thread groups I call in dispatch - only used for mapping thread ID to particle buffer index | |
int3 GroupCount; | |
// Converts raw position into world space position | |
// X and Y are basically UV coordinates, but I subtract 0.5 so it's centered at 0, 0 at the frame center | |
// Z is the depth in world-space meters | |
// W is 1.0 so I can multiply with the transform matrix | |
float3 GetPos(float4 RawPos, float4x4 TransformMatrix) { | |
// Correct for aspect ratio | |
RawPos.x *= FrameRatio; | |
// Project out using depth | |
RawPos.x *= RawPos.z; | |
RawPos.y *= RawPos.z; | |
// Got these values through manual measurement and are specific to the RealSense D435 | |
RawPos.x *= 1.23134; | |
RawPos.y *= 1.23134; | |
// Optional, but I have my depth camera mounted on a HMD so this is necessary for me | |
RawPos = mul(TransformMatrix, RawPos); | |
return RawPos.xyz; | |
} | |
[numthreads(32, 24, 1)] | |
void DepthToPositions(uint3 id : SV_DispatchThreadID) | |
{ | |
uint idx = id.x + (id.y * 32 * GroupCount.x) + (id.z * 32 * GroupsX * 24 * GroupCount.y); | |
Particle CurrentParticle = ParticleBuffer[idx]; | |
int2 PixelPosition = CurrentParticle.PixelPosition; | |
// turns depth texture value (this is from RealSense, so the format is R16 half-precision floating point) into world-space meters | |
// this was years ago, but I'm pretty sure I got the multiplier by experimentation via measuring with my vive controllers lol | |
float RawDepth = DepthTexture[int2(PixelPosition.x, PixelPosition.y)].x; | |
RawDepth *= DepthUnits * DepthScale; | |
CurrentParticle.WorldSpacePosition = GetPos(float4( | |
(PixelPosition.x / FrameSize.x) - 0.5, | |
0.5 - (PixelPosition.y / FrameSize.y), //RealSense depth textures are flipped on the y axis | |
RawDepth, | |
1.0 | |
), TransformMatrix); | |
ParticleBuffer[idx] = CurrentParticle; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment