Skip to content

Commit d4b3e6f

Browse files
fix: fix occlusion in android
1 parent c58a975 commit d4b3e6f

6 files changed

Lines changed: 195 additions & 110 deletions

File tree

ViroRenderer/VROShaderFactory.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,16 +1182,16 @@ std::shared_ptr<VROShaderModifier> VROShaderFactory::createOcclusionDepthModifie
11821182
already has the correct texture coordinate transform applied.
11831183
*/
11841184
std::vector<std::string> modifierCode = {
1185-
// Request the ar_depth_texture sampler via marker
1186-
"// @sampler ar_depth_texture",
1185+
// Use the AO map sampler which is bound to the depth texture by VROSceneRendererARCore
1186+
"uniform sampler2D ao_map;",
11871187

11881188
// Near and far planes - passed as uniforms for dynamic projection matching
11891189
"uniform highp float occlusion_z_near;",
11901190
"uniform highp float occlusion_z_far;",
11911191

11921192
// Sample real-world depth in meters from the depth texture
11931193
// Use diffuse_texcoord directly - it's already transformed for camera orientation
1194-
"highp float z = texture(ar_depth_texture, _surface.diffuse_texcoord).r;",
1194+
"highp float z = texture(ao_map, _surface.diffuse_texcoord).r;",
11951195

11961196
// Use the uniform values for near/far planes
11971197
"highp float n = occlusion_z_near;",
@@ -1213,6 +1213,18 @@ std::shared_ptr<VROShaderModifier> VROShaderFactory::createOcclusionDepthModifie
12131213
VROShaderEntryPoint::Fragment, modifierCode);
12141214
modifier->setName("occlusion_depth");
12151215

1216+
modifier->setUniformBinder("occlusion_z_near", VROShaderProperty::Float,
1217+
[](VROUniform *uniform,
1218+
const VROGeometry *geometry, const VROMaterial *material) {
1219+
uniform->setFloat(0.1f);
1220+
});
1221+
1222+
modifier->setUniformBinder("occlusion_z_far", VROShaderProperty::Float,
1223+
[](VROUniform *uniform,
1224+
const VROGeometry *geometry, const VROMaterial *material) {
1225+
uniform->setFloat(100.0f);
1226+
});
1227+
12161228
return modifier;
12171229
}
12181230

android/sharedCode/src/main/cpp/VROSceneRendererARCore.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,12 @@ void VROSceneRendererARCore::renderWithTracking(const std::shared_ptr<VROARCamer
228228
if (occlusionMode != VROOcclusionMode::Disabled && frame->hasDepthData()) {
229229
depthTexture = frame->getDepthTexture();
230230

231+
// Ensure the depth texture is uploaded to GPU before rendering
232+
// This is critical - without this, the texture exists but contains no data on GPU
233+
if (depthTexture && !depthTexture->isHydrated()) {
234+
depthTexture->prewarm(_driver);
235+
}
236+
231237
// Calculate the transform from Screen UV to Depth Texture UV
232238
// We use the background texture coordinates which match the camera image orientation
233239
VROVector3f BL, BR, TL, TR;
@@ -242,7 +248,7 @@ void VROSceneRendererARCore::renderWithTracking(const std::shared_ptr<VROARCamer
242248
m[1] = TR.y - TL.y; m[5] = BL.y - TL.y; m[9] = 0; m[13] = TL.y;
243249
m[2] = 0; m[6] = 0; m[10]= 1; m[14] = 0;
244250
m[3] = 0; m[7] = 0; m[11]= 0; m[15] = 1;
245-
251+
246252
depthTransform = VROMatrix4f(m);
247253
}
248254

android/sharedCode/src/main/cpp/arcore/VROARFrameARCore.cpp

Lines changed: 22 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -315,122 +315,43 @@ std::shared_ptr<VROARPointCloud> VROARFrameARCore::getPointCloud() {
315315
#pragma mark - Depth Data
316316

317317
void VROARFrameARCore::acquireDepthData() const {
318-
// Only check once per frame
319-
if (_depthDataChecked) {
320-
return;
321-
}
322-
_depthDataChecked = true;
323-
324-
// Reset state
325-
_depthDataAvailable = false;
326-
_depthTexture = nullptr;
327-
_depthConfidenceTexture = nullptr;
328-
_depthWidth = 0;
329-
_depthHeight = 0;
330-
331-
std::shared_ptr<VROARSessionARCore> session = _session.lock();
332-
if (!session) {
333-
return;
334-
}
335-
336-
// Check if depth mode is enabled
337-
if (!session->isDepthModeEnabled()) {
338-
return;
339-
}
340-
341-
std::shared_ptr<VROARSessionARCore> session = _session.lock();
342-
std::shared_ptr<VRODriver> driver = _driver.lock();
343-
if (!session || !driver) {
344-
return;
345-
}
346-
347-
// Acquire depth image from ARCore
348-
arcore::Image *depthImage = nullptr;
349-
arcore::ImageRetrievalStatus status = _frame->acquireDepthImage(&depthImage);
350-
351-
if (status != arcore::ImageRetrievalStatus::Success || depthImage == nullptr) {
352-
// Depth not available for this frame
353-
return;
354-
}
355-
356-
// Get depth image dimensions
357-
_depthWidth = depthImage->getWidth();
358-
_depthHeight = depthImage->getHeight();
359-
360-
if (_depthWidth <= 0 || _depthHeight <= 0) {
361-
delete depthImage;
362-
return;
363-
}
364-
365-
// Get depth data (16-bit depth in millimeters)
366-
const uint8_t *depthData = nullptr;
367-
int depthDataLength = 0;
368-
depthImage->getPlaneData(0, &depthData, &depthDataLength);
369-
370-
if (depthData == nullptr || depthDataLength <= 0) {
371-
delete depthImage;
372-
return;
373-
}
374-
375-
// Create depth texture from the raw data
376-
// ARCore provides depth as 16-bit unsigned integers in millimeters
377-
// Convert to 32-bit float (in meters) for consistency with iOS and shader usage
378-
int numPixels = _depthWidth * _depthHeight;
379-
std::vector<float> floatDepthData(numPixels);
380-
381-
const uint16_t *depthData16 = reinterpret_cast<const uint16_t*>(depthData);
382-
for (int i = 0; i < numPixels; i++) {
383-
// Convert from millimeters (uint16) to meters (float)
384-
floatDepthData[i] = static_cast<float>(depthData16[i]) / 1000.0f;
385-
}
386-
387-
// Create VROData from the float depth data
388-
std::shared_ptr<VROData> depthVROData = std::make_shared<VROData>(
389-
floatDepthData.data(),
390-
floatDepthData.size() * sizeof(float),
391-
VRODataOwnership::Copy);
392-
std::vector<std::shared_ptr<VROData>> dataVec = { depthVROData };
393-
394-
// Create the depth texture using R32F format
395-
_depthTexture = std::make_shared<VROTexture>(VROTextureType::Texture2D,
396-
VROTextureFormat::R32F,
397-
VROTextureInternalFormat::R32F,
398-
false, // not sRGB
399-
VROMipmapMode::None,
400-
dataVec,
401-
_depthWidth, _depthHeight,
402-
std::vector<uint32_t>());
403-
404-
_depthDataAvailable = true;
405-
406-
// Clean up
407-
delete depthImage;
408-
409-
pinfo("VROARFrameARCore: Acquired depth data %dx%d", _depthWidth, _depthHeight);
318+
// Deprecated: Depth data is now managed by VROARSessionARCore
410319
}
411320

412321
std::shared_ptr<VROTexture> VROARFrameARCore::getDepthTexture() {
413-
acquireDepthData();
414-
return _depthTexture;
322+
std::shared_ptr<VROARSessionARCore> session = _session.lock();
323+
if (session) {
324+
return session->getDepthTexture();
325+
}
326+
return nullptr;
415327
}
416328

417329
std::shared_ptr<VROTexture> VROARFrameARCore::getDepthConfidenceTexture() {
418-
// Confidence texture acquisition can be implemented similarly
419-
// For now, return nullptr as it's optional
420-
return _depthConfidenceTexture;
330+
return nullptr;
421331
}
422332

423333
bool VROARFrameARCore::hasDepthData() const {
424-
acquireDepthData();
425-
return _depthDataAvailable;
334+
std::shared_ptr<VROARSessionARCore> session = _session.lock();
335+
if (session) {
336+
return session->getDepthTexture() != nullptr;
337+
}
338+
return false;
426339
}
427340

428341
int VROARFrameARCore::getDepthImageWidth() const {
429-
return _depthWidth;
342+
std::shared_ptr<VROARSessionARCore> session = _session.lock();
343+
if (session && session->getDepthTexture()) {
344+
return session->getDepthTexture()->getWidth();
345+
}
346+
return 0;
430347
}
431348

432349
int VROARFrameARCore::getDepthImageHeight() const {
433-
return _depthHeight;
350+
std::shared_ptr<VROARSessionARCore> session = _session.lock();
351+
if (session && session->getDepthTexture()) {
352+
return session->getDepthTexture()->getHeight();
353+
}
354+
return 0;
434355
}
435356

436357
#pragma mark - Scene Semantics

android/sharedCode/src/main/cpp/arcore/VROARFrameARCore.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,7 @@ class VROARFrameARCore : public VROARFrame {
112112
std::weak_ptr<VRODriver> _driver;
113113

114114
// Cached depth texture (refreshed each frame)
115-
mutable std::shared_ptr<VROTexture> _depthTexture;
116115
mutable std::shared_ptr<VROTexture> _depthConfidenceTexture;
117-
mutable int _depthWidth = 0;
118-
mutable int _depthHeight = 0;
119-
mutable bool _depthDataAvailable = false;
120116
mutable bool _depthDataChecked = false;
121117

122118
// Cached semantic data (refreshed each frame)

android/sharedCode/src/main/cpp/arcore/VROARSessionARCore.cpp

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include "VROARAnchor.h"
2929
#include "VROGeospatialAnchor.h"
3030
#include "VROARHitTestResult.h"
31+
#include "VROTextureSubstrateOpenGL.h"
32+
#include "VRODriverOpenGL.h"
3133
#include "VROARImageTargetAndroid.h"
3234
#include "VROARPlaneAnchor.h"
3335
#include "VROCameraTexture.h"
@@ -61,11 +63,18 @@ VROARSessionARCore::VROARSessionARCore(std::shared_ptr<VRODriverOpenGL> driver)
6163
_geospatialMode(arcore::GeospatialMode::Disabled),
6264
_cameraTextureId(0),
6365
_displayRotation(VROARDisplayRotation::R0), _rotatedImageDataLength(0),
64-
_rotatedImageData(nullptr) {
66+
_rotatedImageData(nullptr),
67+
_driver(driver) {
6568

6669
_session = nullptr;
6770
_frame = nullptr;
6871
_frameCount = 0;
72+
73+
// Sync occlusion mode with depth mode default
74+
// Since depth mode defaults to Automatic, enable occlusion by default
75+
if (_depthMode == arcore::DepthMode::Automatic) {
76+
VROARSession::setOcclusionMode(VROOcclusionMode::DepthBased);
77+
}
6978
}
7079

7180
void VROARSessionARCore::setARCoreSession(
@@ -717,7 +726,9 @@ std::unique_ptr<VROARFrame> &VROARSessionARCore::updateFrame() {
717726
std::make_unique<VROARFrameARCore>(_frame, _viewport, shared_from_this());
718727

719728
VROARFrameARCore *arFrame = (VROARFrameARCore *)_currentFrame.get();
729+
arFrame->setDriver(_driver.lock());
720730
processUpdatedAnchors(arFrame);
731+
updateDepthTexture();
721732

722733
return _currentFrame;
723734
}
@@ -1591,3 +1602,124 @@ void VROARSessionARCore::setSemanticModeEnabled(bool enabled) {
15911602
_semanticModeEnabled = false;
15921603
}
15931604
}
1605+
1606+
void VROARSessionARCore::updateDepthTexture() {
1607+
// Limit log frequency to avoid spam
1608+
static int logCounter = 0;
1609+
if (logCounter++ % 60 == 0) {
1610+
pinfo("VROARSessionARCore::updateDepthTexture called (sampled)");
1611+
}
1612+
1613+
if (!isDepthModeEnabled()) {
1614+
// pinfo("VROARSessionARCore: Depth mode disabled, skipping update");
1615+
return;
1616+
}
1617+
1618+
// Acquire depth image from ARCore
1619+
arcore::Image *depthImage = nullptr;
1620+
arcore::ImageRetrievalStatus status = _frame->acquireDepthImage(&depthImage);
1621+
1622+
if (status != arcore::ImageRetrievalStatus::Success || depthImage == nullptr) {
1623+
// pwarn("VROARSessionARCore: Failed to acquire depth image. Status: %d", (int)status);
1624+
return;
1625+
}
1626+
1627+
int width = depthImage->getWidth();
1628+
int height = depthImage->getHeight();
1629+
1630+
if (width <= 0 || height <= 0) {
1631+
pwarn("VROARSessionARCore: Invalid depth image dimensions: %d x %d", width, height);
1632+
delete depthImage;
1633+
return;
1634+
}
1635+
1636+
// Get depth data (16-bit depth in millimeters)
1637+
const uint8_t *depthData = nullptr;
1638+
int depthDataLength = 0;
1639+
depthImage->getPlaneData(0, &depthData, &depthDataLength);
1640+
1641+
int rowStride = depthImage->getPlaneRowStride(0);
1642+
1643+
if (depthData == nullptr || depthDataLength <= 0) {
1644+
pwarn("VROARSessionARCore: Invalid depth data. Length: %d", depthDataLength);
1645+
delete depthImage;
1646+
return;
1647+
}
1648+
1649+
// Convert to float buffer
1650+
int numPixels = width * height;
1651+
if (_depthFloatBuffer.size() != numPixels) {
1652+
_depthFloatBuffer.resize(numPixels);
1653+
}
1654+
1655+
float *floatData = _depthFloatBuffer.data();
1656+
1657+
// Handle row stride (padding)
1658+
if (rowStride > 0 && rowStride != width * 2) {
1659+
for (int y = 0; y < height; y++) {
1660+
const uint16_t *rowStart = reinterpret_cast<const uint16_t*>(depthData + y * rowStride);
1661+
for (int x = 0; x < width; x++) {
1662+
floatData[y * width + x] = (float)rowStart[x] * 0.001f;
1663+
}
1664+
}
1665+
} else {
1666+
// Optimized loop: direct pointer access (packed)
1667+
const uint16_t *depthData16 = reinterpret_cast<const uint16_t*>(depthData);
1668+
for (int i = 0; i < numPixels; i++) {
1669+
floatData[i] = (float)depthData16[i] * 0.001f; // mm to meters
1670+
}
1671+
}
1672+
1673+
// DEBUG: Log center depth value
1674+
if (numPixels > 0) {
1675+
int centerIdx = (height / 2) * width + (width / 2);
1676+
// pinfo("VROARSessionARCore: Depth update. Center val: %f, Width: %d, Height: %d", floatData[centerIdx], width, height);
1677+
}
1678+
1679+
// If texture doesn't exist, create it
1680+
if (!_depthTexture || _depthTexture->getWidth() != width || _depthTexture->getHeight() != height) {
1681+
pinfo("VROARSessionARCore: Creating new depth texture (size %d x %d)", width, height);
1682+
std::shared_ptr<VROData> depthVROData = std::make_shared<VROData>(
1683+
(void *)floatData, numPixels * sizeof(float), VRODataOwnership::Copy);
1684+
std::vector<std::shared_ptr<VROData>> dataVec = { depthVROData };
1685+
1686+
_depthTexture = std::make_shared<VROTexture>(VROTextureType::Texture2D,
1687+
VROTextureFormat::R32F,
1688+
VROTextureInternalFormat::R32F,
1689+
false,
1690+
VROMipmapMode::None,
1691+
dataVec,
1692+
width, height,
1693+
std::vector<uint32_t>());
1694+
1695+
_depthTexture->setMinificationFilter(VROFilterMode::Nearest);
1696+
_depthTexture->setMagnificationFilter(VROFilterMode::Nearest);
1697+
// Use Clamp which maps to GL_CLAMP_TO_EDGE for OpenGL ES compatibility
1698+
_depthTexture->setWrapS(VROWrapMode::Clamp);
1699+
_depthTexture->setWrapT(VROWrapMode::Clamp);
1700+
} else {
1701+
// Update existing texture
1702+
std::shared_ptr<VRODriver> driver = _driver.lock();
1703+
if (driver) {
1704+
VROTextureSubstrate *substrate = _depthTexture->getSubstrate(0, driver, true);
1705+
if (substrate) {
1706+
// We need to cast to OpenGL substrate to access GL ID, or use a generic update method if available.
1707+
// Since we are in VROARSessionARCore (Android specific), we can assume OpenGL.
1708+
VROTextureSubstrateOpenGL *glSubstrate = (VROTextureSubstrateOpenGL *)substrate;
1709+
std::pair<GLenum, GLuint> textureInfo = glSubstrate->getTexture();
1710+
GLenum target = textureInfo.first;
1711+
GLuint texId = textureInfo.second;
1712+
1713+
glBindTexture(target, texId);
1714+
glTexSubImage2D(target, 0, 0, 0, width, height, GL_RED, GL_FLOAT, floatData);
1715+
glBindTexture(target, 0);
1716+
} else {
1717+
pwarn("VROARSessionARCore: Failed to get substrate for depth texture update");
1718+
}
1719+
} else {
1720+
pwarn("VROARSessionARCore: Driver expired, cannot update depth texture");
1721+
}
1722+
}
1723+
1724+
delete depthImage;
1725+
}

0 commit comments

Comments
 (0)