Skip to content

Commit 47f7c35

Browse files
committed
Fixed depth calculations (inverse depth is 1/d, not 1 - d). Absolute depth is now inferred from inverse depth by exposing a scale factor as a material property.
1 parent 78b6a09 commit 47f7c35

File tree

4 files changed

+61
-51
lines changed

4 files changed

+61
-51
lines changed

Packages/com.doji.genesis/Editor/DepthSkyboxPrefabUtility.cs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Genesis.Editor {
99
public static class DepthSkyboxPrefabUtility {
1010

1111
/// <summary>
12-
/// Imput given png fileb, generates depth and creates a prefab for a DepthSkybox.
12+
/// Given an input png file, generates depth and creates a prefab for a DepthSkybox.
1313
/// </summary>
1414
public static void CreateSkyboxAsset(string pngFilePath) {
1515
string name = Path.GetFileNameWithoutExtension(pngFilePath);
@@ -18,8 +18,8 @@ public static void CreateSkyboxAsset(string pngFilePath) {
1818

1919
string pngTargetPath = Path.Combine(assetPath, $"{name}_rgb.png");
2020
Texture2D skybox = ImportImageFile(pngFilePath, pngTargetPath);
21-
GenerateDepth(assetPath, name, skybox);
22-
CreateSkyboxPrefab(assetPath, name);
21+
var range = GenerateDepth(assetPath, name, skybox);
22+
CreateSkyboxPrefab(assetPath, name, range);
2323
}
2424

2525
/// <summary>
@@ -31,27 +31,31 @@ public static async Task CreateSkyboxAsset(string id, string name) {
3131

3232
string imageFile = Path.Combine(assetPath, $"{name}_rgb.png");
3333
Texture2D skybox = await DownloadSkyboxById(imageFile, id);
34-
GenerateDepth(assetPath, name, skybox);
35-
CreateSkyboxPrefab(assetPath, name);
34+
var range = GenerateDepth(assetPath, name, skybox);
35+
CreateSkyboxPrefab(assetPath, name, range);
3636
}
3737

38-
private static void GenerateDepth(string assetPath, string name, Texture2D skybox) {
38+
private static Vector2 GenerateDepth(string assetPath, string name, Texture2D skybox) {
3939
int progressId = Progress.Start("Generating depth texture", "Generating a depth texture from skybox...");
4040

4141
DepthEstimator depthEstimator = new DepthEstimator();
4242
depthEstimator.GenerateDepth(skybox);
43-
var depthTexture = depthEstimator.GetNormalizedDepth();
43+
var depthTexture = depthEstimator.PostProcessDepth();
4444

4545
string depthTextureFile = Path.Combine(assetPath, $"{name}_depth.asset");
4646
CreateAsset(depthTexture, depthTextureFile);
47-
AssetDatabase.SaveAssets();
48-
AssetDatabase.Refresh();
4947

50-
// for some reason, saving out as exr or png and reimporting produces
48+
// for some reason, saving out as exr or png and reimporting produces what looks like precision artifacts
5149
//byte[] bytes = depthTexture.EncodeToEXR(Texture2D.EXRFlags.OutputAsFloat);
5250

5351
depthEstimator.Dispose();
52+
53+
AssetDatabase.SaveAssets();
54+
AssetDatabase.Refresh();
55+
5456
Progress.Remove(progressId);
57+
58+
return new Vector2(depthEstimator.MinDepth, depthEstimator.MaxDepth);
5559
}
5660

5761
/// <summary>
@@ -66,7 +70,9 @@ private static void CreateAsset(Object obj, string path) {
6670
AssetDatabase.CreateAsset(obj, path);
6771
}
6872

69-
public static void CreateSkyboxPrefab(string assetPath, string name) {
73+
public static void CreateSkyboxPrefab(string assetPath, string name, Vector2 range) {
74+
int progressId = Progress.Start("Creating skybox assets", "Your skybox assets are being created...");
75+
7076
GameObject skyboxPrefab = (GameObject)Resources.Load("Prefabs/DepthSkybox");
7177

7278
GameObject instance = (GameObject)PrefabUtility.InstantiatePrefab(skyboxPrefab);
@@ -82,6 +88,8 @@ public static void CreateSkyboxPrefab(string assetPath, string name) {
8288
renderer.sharedMaterial = m;
8389
m.SetTexture("_MainTex", skybox);
8490
m.SetTexture("_Depth", skyboxDepth);
91+
m.SetFloat("_Min", range.x);
92+
m.SetFloat("_Max", range.y);
8593

8694
string materialPath = Path.Combine(assetPath, $"{name}_material.mat");
8795
CreateAsset(m, materialPath);
@@ -93,8 +101,12 @@ public static void CreateSkyboxPrefab(string assetPath, string name) {
93101
}
94102
GameObject variant = PrefabUtility.SaveAsPrefabAsset(instance, prefabPath);
95103
Object.DestroyImmediate(instance);
96-
97104
PrefabUtility.InstantiatePrefab(variant);
105+
106+
AssetDatabase.SaveAssets();
107+
AssetDatabase.Refresh();
108+
109+
Progress.Remove(progressId);
98110
}
99111

100112
/// <summary>

Packages/com.doji.genesis/Runtime/Materials/EquirectDepth.mat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ Material:
6969
- _GlossMapScale: 1
7070
- _Glossiness: 0.5
7171
- _GlossyReflections: 1
72-
- _MaxDepth: 100
72+
- _Max: 1000
7373
- _Metallic: 0
74-
- _MinDepth: 2
7574
- _Mode: 0
7675
- _OcclusionStrength: 1
7776
- _Parallax: 0.02
77+
- _Scale: 1
7878
- _SmoothnessTextureChannel: 0
7979
- _SpecularHighlights: 1
8080
- _SrcBlend: 1

Packages/com.doji.genesis/Runtime/Scripts/DepthEstimator.cs

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Linq;
33
using Unity.Barracuda;
4+
using Unity.Collections;
45
using UnityEngine;
56

67
namespace Genesis {
@@ -20,12 +21,8 @@ public static NNModel MiDaSv2 {
2021
public RenderTexture _input, _output;
2122
private int _width, _height;
2223

23-
private float MinDepth { get; set; }
24-
private float MaxDepth { get; set; }
25-
26-
// Shader Properties
27-
private static readonly int _minShaderProp = Shader.PropertyToID("_Min");
28-
private static readonly int _maxShaderProp = Shader.PropertyToID("_Max");
24+
public float MinDepth { get; private set; }
25+
public float MaxDepth { get; private set; }
2926

3027
public DepthEstimator() {
3128
InitializeNetwork();
@@ -49,20 +46,6 @@ public RenderTexture GenerateDepth(Texture2D inputTexture) {
4946
return _output;
5047
}
5148

52-
public void SetProperties(Material mat) {
53-
// In Barracuda 1.0.4 the output of MiDaS can be passed directly to a texture as it is shaped correctly.
54-
// In later versions we have to swap X and Y axes, and also flip the X axis...
55-
// We need to inform the shader of this change.
56-
#if BARRACUDA_1_0_5_OR_NEWER
57-
mat.SetInt("_SwapChannels", 1);
58-
#else
59-
mat.SetInt("_SwapChannels", 0);
60-
#endif
61-
62-
mat.SetFloat(_minShaderProp, MinDepth);
63-
mat.SetFloat(_maxShaderProp, MaxDepth);
64-
}
65-
6649
/// <summary>
6750
/// Loads the <see cref="NNModel"/> asset in memory and creates a Barracuda <see cref="IWorker"/>
6851
/// </summary>
@@ -89,24 +72,39 @@ private void InitializeNetwork() {
8972
#endif
9073
}
9174

92-
public Texture2D GetNormalizedDepth() {
75+
/// <summary>
76+
/// Do some post processing of the depth texture to
77+
/// - fix depth discontinuities / seams
78+
/// - fix distortions at the poles
79+
/// - normalize depth values
80+
/// </summary>
81+
public Texture2D PostProcessDepth() {
9382
RenderTexture depth = _output;
94-
Texture2D depthTexture = new Texture2D(depth.width, depth.height, TextureFormat.RFloat, false);
83+
Texture2D depthTexture = new Texture2D(depth.width, depth.height, TextureFormat.RFloat, mipChain: false, linear: true);
84+
depthTexture.wrapModeU = TextureWrapMode.Clamp;
85+
depthTexture.wrapModeV = TextureWrapMode.Repeat;
9586
RenderTexture.active = depth;
9687
depthTexture.ReadPixels(new Rect(0, 0, depth.width, depth.height), 0, 0);
9788
RenderTexture.active = null;
9889

99-
//noramlize to range [0, 1] and convert from MiDaS' reversed depth to depth
10090
var depthData = depthTexture.GetPixelData<float>(0);
101-
float min = MinDepth;
102-
float max = MaxDepth;
91+
92+
NormalizeDepth(depthData);
93+
94+
depthTexture.Apply(false);
95+
return depthTexture;
96+
}
97+
98+
/// <summary>
99+
/// Makes sure all values of the depth texture are in the [0, 1] range
100+
/// and converts from MiDaS' reversed depth to depth.
101+
/// </summary>
102+
private void NormalizeDepth(NativeArray<float> depthData) {
103103
for (int i = 0; i < depthData.Length; i++) {
104-
float depthValue = depthData[i];
105-
float normalizedDepth = 1.0f - Mathf.Clamp01((depthValue - min) / (max - min));
104+
float depth = depthData[i];
105+
float normalizedDepth = Mathf.Clamp01((depth - MinDepth) / (MaxDepth - MinDepth));
106106
depthData[i] = normalizedDepth;
107107
}
108-
depthTexture.Apply(false);
109-
return depthTexture;
110108
}
111109

112110
/// <summary>
@@ -124,7 +122,7 @@ private void AllocateObjects() {
124122

125123
// Declare texture resources
126124
_input = RenderTexture.GetTemporary(_width, _height, 0, RenderTextureFormat.ARGB32);
127-
_output = RenderTexture.GetTemporary(_width, _height, 0, RenderTextureFormat.RFloat);
125+
_output = RenderTexture.GetTemporary(_width, _height, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
128126
}
129127

130128
/// <summary>

Packages/com.doji.genesis/Runtime/Shaders/EquirectDepth.shader

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ Shader "Genesis/EquirectDepth" {
22
Properties {
33
_MainTex ("Texture", 2D) = "white" {}
44
_Depth("Depth", 2D) = "white" {}
5-
_MinDepth("Min Depth", Range(0.0, 100.0)) = 2.0
6-
_MaxDepth("Max Depth", Range(10.0, 10000.0)) = 100.0
5+
_Scale("Depth Multiplier", float) = 1
6+
_Max("Max Depth Cutoff", float) = 1000
77
}
88
SubShader {
99
Tags { "RenderType"="Opaque" }
@@ -20,8 +20,9 @@ Shader "Genesis/EquirectDepth" {
2020
float4 _MainTex_ST;
2121
sampler2D _Depth;
2222

23-
float _MinDepth;
24-
float _MaxDepth;
23+
float _Min;
24+
float _Max;
25+
float _Scale;
2526

2627
struct appdata {
2728
float4 vertex : POSITION;
@@ -46,9 +47,8 @@ Shader "Genesis/EquirectDepth" {
4647
uv.x = 1 - uv.x; // invert x because we use an outward-facing sphere with 'Cull Front'
4748

4849
float depth = tex2Dlod(_Depth, float4(uv, 0, 0));
49-
50-
// assume normalized depth, map to a given min, max range
51-
depth = (depth * _MaxDepth) + _MinDepth;
50+
depth = _Scale / (depth);
51+
depth = clamp(depth, 0, _Max * _Scale);
5252

5353
// Vertex displacement (assumes rendering on a unit sphere with radius 1)
5454
o.vertex = UnityObjectToClipPos(v.vertex * depth);

0 commit comments

Comments
 (0)