Skip to content

Commit ec1d837

Browse files
authored
Fix missing camera pose handling and skybox gamma correction (#199)
1 parent 155ee6b commit ec1d837

File tree

4 files changed

+46
-25
lines changed

4 files changed

+46
-25
lines changed

src/camera-manager.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ class CameraManager {
4444
constructor(global: Global, bbox: BoundingBox, collider: VoxelCollider | null = null) {
4545
const { config, events, settings, state } = global;
4646

47-
const camera0 = settings.cameras[0].initial;
48-
const frameCamera = createFrameCamera(bbox, camera0.fov);
49-
const resetCamera = createCamera(new Vec3(camera0.position), new Vec3(camera0.target), camera0.fov);
47+
const camera0 = settings.cameras[0]?.initial;
48+
const defaultFov = camera0?.fov ?? 75;
49+
const frameCamera = createFrameCamera(bbox, defaultFov);
50+
const resetCamera = camera0 ?
51+
createCamera(new Vec3(camera0.position), new Vec3(camera0.target), camera0.fov) :
52+
frameCamera;
5053

5154
const getAnimTrack = (initial: Camera, isObjectExperience: boolean) => {
5255
const { animTracks } = settings;
@@ -65,7 +68,7 @@ class CameraManager {
6568

6669
// object experience starts outside the bounding box
6770
const isObjectExperience = !bbox.containsPoint(resetCamera.position);
68-
const animTrack = getAnimTrack(settings.hasStartPose ? resetCamera : frameCamera, isObjectExperience);
71+
const animTrack = getAnimTrack(resetCamera, isObjectExperience);
6972

7073
const controllers = {
7174
orbit: new OrbitController(),

src/schemas/v2.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ type ExperienceSettings = {
7878
cameras: Camera[],
7979
annotations: Annotation[],
8080

81-
startMode: 'default' | 'animTrack' | 'annotation',
82-
83-
hasStartPose?: boolean
81+
startMode: 'default' | 'animTrack' | 'annotation'
8482
};
8583

8684
export type { AnimTrack, Camera, Annotation, PostEffectSettings, ExperienceSettings };

src/settings.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,15 @@ const migrateV2 = (v1: V1): V2 => {
8787
animTracks: v1.animTracks.map((animTrackV1: AnimTrackV1) => {
8888
return migrateAnimTrackV2(animTrackV1, v1.camera.fov || 60);
8989
}),
90-
cameras: [{
90+
cameras: (v1.camera.position && v1.camera.target) ? [{
9191
initial: {
92-
position: (v1.camera.position || [0, 0, 5]) as [number, number, number],
93-
target: (v1.camera.target || [0, 0, 0]) as [number, number, number],
92+
position: v1.camera.position as [number, number, number],
93+
target: v1.camera.target as [number, number, number],
9494
fov: v1.camera.fov || 75
9595
}
96-
}],
96+
}] : [],
9797
annotations: [],
98-
startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default',
99-
hasStartPose: !!(v1.camera.position && v1.camera.target)
98+
startMode: v1.camera.startAnim === 'animTrack' ? 'animTrack' : 'default'
10099
};
101100
};
102101

src/viewer.ts

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ class Viewer {
133133

134134
origChunks: {
135135
glsl: {
136-
gsplatOutputVS: string
136+
gsplatOutputVS: string,
137+
skyboxPS: string
137138
},
138139
wgsl: {
139-
gsplatOutputVS: string
140+
gsplatOutputVS: string,
141+
skyboxPS: string
140142
}
141143
};
142144

@@ -149,22 +151,24 @@ class Viewer {
149151
// enable anonymous CORS for image loading in safari
150152
(app.loader.getHandler('texture') as TextureHandler).imgParser.crossOrigin = 'anonymous';
151153

152-
this.origChunks = {
153-
glsl: {
154-
gsplatOutputVS: ShaderChunks.get(graphicsDevice, 'glsl').get('gsplatOutputVS')
155-
},
156-
wgsl: {
157-
gsplatOutputVS: ShaderChunks.get(graphicsDevice, 'wgsl').get('gsplatOutputVS')
158-
}
159-
};
160-
161154
// render skybox as plain equirect
162155
const glsl = ShaderChunks.get(graphicsDevice, 'glsl');
163156
glsl.set('skyboxPS', glsl.get('skyboxPS').replace('mapRoughnessUv(uv, mipLevel)', 'uv'));
164157

165158
const wgsl = ShaderChunks.get(graphicsDevice, 'wgsl');
166159
wgsl.set('skyboxPS', wgsl.get('skyboxPS').replace('mapRoughnessUv(uv, uniform.mipLevel)', 'uv'));
167160

161+
this.origChunks = {
162+
glsl: {
163+
gsplatOutputVS: glsl.get('gsplatOutputVS'),
164+
skyboxPS: glsl.get('skyboxPS')
165+
},
166+
wgsl: {
167+
gsplatOutputVS: wgsl.get('gsplatOutputVS'),
168+
skyboxPS: wgsl.get('skyboxPS')
169+
}
170+
};
171+
168172
// disable auto render, we'll render only when camera changes
169173
app.autoRender = false;
170174

@@ -476,6 +480,21 @@ class Viewer {
476480
ShaderChunks.get(app.graphicsDevice, 'glsl').set('gsplatOutputVS', gammaChunkGlsl);
477481
ShaderChunks.get(app.graphicsDevice, 'wgsl').set('gsplatOutputVS', gammaChunkWgsl);
478482

483+
// force skybox shader to write gamma-space colors (inline pow replaces the
484+
// gammaCorrectOutput call which is a no-op under CameraFrame's GAMMA_NONE)
485+
ShaderChunks.get(app.graphicsDevice, 'glsl').set('skyboxPS',
486+
this.origChunks.glsl.skyboxPS.replace(
487+
'gammaCorrectOutput(toneMap(processEnvironment(linear)))',
488+
'pow(toneMap(processEnvironment(linear)) + 0.0000001, vec3(1.0 / 2.2))'
489+
)
490+
);
491+
ShaderChunks.get(app.graphicsDevice, 'wgsl').set('skyboxPS',
492+
this.origChunks.wgsl.skyboxPS.replace(
493+
'gammaCorrectOutput(toneMap(processEnvironment(linear)))',
494+
'pow(toneMap(processEnvironment(linear)) + 0.0000001, vec3f(1.0 / 2.2))'
495+
)
496+
);
497+
479498
// ensure the final compose blit doesn't perform linear->gamma conversion.
480499
RenderTarget.prototype.isColorBufferSrgb = function (index) {
481500
return this === app.graphicsDevice.backBuffer ? true : origIsColorBufferSrgb.call(this, index);
@@ -489,9 +508,11 @@ class Viewer {
489508
this.cameraFrame = null;
490509
}
491510

492-
// restore gsplat output shader chunks to engine defaults
511+
// restore shader chunks to engine defaults
493512
ShaderChunks.get(app.graphicsDevice, 'glsl').set('gsplatOutputVS', this.origChunks.glsl.gsplatOutputVS);
494513
ShaderChunks.get(app.graphicsDevice, 'wgsl').set('gsplatOutputVS', this.origChunks.wgsl.gsplatOutputVS);
514+
ShaderChunks.get(app.graphicsDevice, 'glsl').set('skyboxPS', this.origChunks.glsl.skyboxPS);
515+
ShaderChunks.get(app.graphicsDevice, 'wgsl').set('skyboxPS', this.origChunks.wgsl.skyboxPS);
495516

496517
// restore original isColorBufferSrgb behavior
497518
RenderTarget.prototype.isColorBufferSrgb = origIsColorBufferSrgb;

0 commit comments

Comments
 (0)