-
Notifications
You must be signed in to change notification settings - Fork 52
/
depth_camera_fs.glsl
186 lines (160 loc) · 5.24 KB
/
depth_camera_fs.glsl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Copyright (C) 2018 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#version 330
in block
{
vec2 uv0;
vec3 cameraDir;
} inPs;
uniform sampler2D depthTexture;
uniform sampler2D colorTexture;
uniform sampler2D particleTexture;
uniform sampler2D particleDepthTexture;
out vec4 fragColor;
uniform vec2 projectionParams;
uniform float near;
uniform float far;
uniform float min;
uniform float max;
uniform vec3 backgroundColor;
uniform float particleStddev;
uniform float particleScatterRatio;
// rnd is a random number in the range of [0-1]
uniform float rnd;
float packFloat(vec4 color)
{
int rgba = (int(color.x * 255.0) << 24) +
(int(color.y * 255.0) << 16) +
(int(color.z * 255.0) << 8) +
int(color.w * 255.0);
return intBitsToFloat(rgba);
}
// see gaussian_noise_fs.glsl for documentation on the rand and gaussrand
// functions
#define PI 3.14159265358979323846264
float rand(vec2 co)
{
float r = fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);
// Make sure that we don't return 0.0
if(r == 0.0)
return 0.000000000001;
else
return r;
}
vec4 gaussrand(vec2 co, vec3 offsets, float stddev, float mean)
{
float U, V, R, Z;
U = rand(co + vec2(offsets.x, offsets.x));
V = rand(co + vec2(offsets.y, offsets.y));
R = rand(co + vec2(offsets.z, offsets.z));
if(R < 0.5)
Z = sqrt(-2.0 * log(U)) * sin(2.0 * PI * V);
else
Z = sqrt(-2.0 * log(U)) * cos(2.0 * PI * V);
Z = Z * stddev + mean;
return vec4(Z, Z, Z, 0.0);
}
void main()
{
float tolerance = 1e-6;
// get linear depth
float fDepth = texture(depthTexture, inPs.uv0).x;
float d = projectionParams.y / (fDepth - projectionParams.x);
// reconstruct 3d viewspace pos from depth
vec3 viewSpacePos = inPs.cameraDir * d;
// convert to z up
vec3 point = vec3(-viewSpacePos.z, -viewSpacePos.x, viewSpacePos.y);
// color
vec4 color = texture(colorTexture, inPs.uv0);
// particle mask - color and depth
vec4 particle = texture(particleTexture, inPs.uv0);
float particleDepth = texture(particleDepthTexture, inPs.uv0).x;
// return particle depth if it can be seen by the camera and not obstructed
// by other objects in the camera view
if (particle.x > 0 && particleDepth < fDepth)
{
// apply scatter effect so that only some of the smoke pixels are visible
float r = rand(inPs.uv0 + vec2(rnd, rnd));
if (r < particleScatterRatio)
{
// set point to 3d pos of particle pixel
float pd = projectionParams.y / (particleDepth - projectionParams.x);
vec3 particleViewSpacePos = inPs.cameraDir * pd;
vec3 particlePoint = vec3(-particleViewSpacePos.z, -particleViewSpacePos.x,
particleViewSpacePos.y);
float rr = rand(inPs.uv0 + vec2(rnd, rnd)) - 0.5;
// apply gaussian noise to particle point cloud data
// With large particles, the range returned are all from the first large
// particle. So add noise with some mean values so that all the points are
// shifted further out. This gives depth readings beyond the first few
// particles and avoid too many early returns
vec3 noise = gaussrand(inPs.uv0, vec3(rnd, rnd, rnd),
particleStddev, rr*rr*particleStddev*0.5).xyz;
float noiseLength = length(noise);
float particlePointLength = length(particlePoint);
float newLength = particlePointLength + noiseLength;
vec3 newPoint = particlePoint * (newLength / particlePointLength);
// make sure we do not produce depth values larger than depth of first
// non-particle obstacle, e.g. a box behind particle should still return
// a hit
float pointLength = length(point);
if (newLength < pointLength)
point = newPoint;
}
}
// clamp xyz and set rgb to background color
if (point.x > far - tolerance)
{
if (isinf(max))
{
point = vec3(max);
}
else
{
point.x = max;
}
// clamp to background color only if it is not a particle pixel
// this is because point.x may have been set to background depth value
// due to the scatter effect. We should still render particles in the color
// image
if (particle.x < 1e-6)
{
color = vec4(backgroundColor, 1.0);
}
}
else if (point.x < near + tolerance)
{
if (isinf(min))
{
point = vec3(min);
}
else
{
point.x = min;
}
// clamp to background color only if it is not a particle pixel
if (particle.x < 1e-6)
{
color = vec4(backgroundColor, 1.0);
}
}
// gamma correct - using same method as:
// https://bitbucket.org/sinbad/ogre/src/v2-1/Samples/Media/Hlms/Pbs/GLSL/PixelShader_ps.glsl#lines-513
color = sqrt(color);
float rgba = packFloat(color);
fragColor = vec4(point, rgba);
}