Implement two-pass separable Gaussian blur for camera preview
Replace the single-pass 9-tap directional blur with a three-pass pipeline: passthrough (camera→FBO), horizontal blur (FBO-A→FBO-B), vertical blur (FBO-B→screen). This produces a true 2D Gaussian with a 13-tap kernel per pass, eliminating the visible banding/streaking of the old approach. Key changes: - TiltShiftRenderer: FBO ping-pong with two color textures, separate fullscreen quad for blur passes (no crop-to-fill), drawQuad helper - TiltShiftShader: manages two programs (passthrough + blur), blur program uses raw screen-space angle (no camera rotation adjustment) - tiltshift_fragment.glsl: rewritten for sampler2D in screen space, aspect correction on X axis (height-normalized), uBlurDirection uniform for H/V selection, wider falloff (3x multiplier) - New tiltshift_passthrough_fragment.glsl for camera→FBO copy - TiltShiftOverlay: shrink PINCH_SIZE zone (1.3x, was 2.0x) so pinch-to-zoom is reachable over more of the screen - CameraManager: optimistic zoom update fixes pinch-to-zoom stalling (stale zoomRatio base prevented delta accumulation) Bump version to 1.1.3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
aab1ff38a4
commit
f3baa723be
7 changed files with 397 additions and 298 deletions
|
|
@ -174,24 +174,14 @@ class CameraManager(private val context: Context) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets the zoom ratio. Updates UI state only after the camera confirms the change.
|
||||
* Sets the zoom ratio. Updates UI state immediately so that rapid pinch-to-zoom
|
||||
* gestures accumulate correctly (each frame uses the latest ratio as its base).
|
||||
* If the camera rejects the value, the next successful set corrects the state.
|
||||
*/
|
||||
fun setZoom(ratio: Float) {
|
||||
val clamped = ratio.coerceIn(_minZoomRatio.value, _maxZoomRatio.value)
|
||||
val future = camera?.cameraControl?.setZoomRatio(clamped)
|
||||
if (future != null) {
|
||||
future.addListener({
|
||||
try {
|
||||
future.get()
|
||||
_zoomRatio.value = clamped
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Zoom operation failed", e)
|
||||
}
|
||||
}, ContextCompat.getMainExecutor(context))
|
||||
} else {
|
||||
// Optimistic update when camera not available (e.g. during init)
|
||||
_zoomRatio.value = clamped
|
||||
}
|
||||
_zoomRatio.value = clamped
|
||||
camera?.cameraControl?.setZoomRatio(clamped)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue