Add front camera texture coordinate handling

- Add separate texture coordinates for front and back cameras
- Front camera uses mirrored coordinates for natural selfie view
- Add setFrontCamera() method to renderer for dynamic switching
- Update texture coord buffer on GL thread when camera changes
- CameraScreen observes isFrontCamera state to trigger updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-01-29 17:03:26 +01:00
commit b16dd971f2
2 changed files with 48 additions and 4 deletions

View file

@ -36,6 +36,9 @@ class TiltShiftRenderer(
@Volatile @Volatile
var blurParameters: BlurParameters = BlurParameters.DEFAULT var blurParameters: BlurParameters = BlurParameters.DEFAULT
@Volatile
private var isFrontCamera: Boolean = false
// Quad vertices (full screen) // Quad vertices (full screen)
private val vertices = floatArrayOf( private val vertices = floatArrayOf(
-1f, -1f, // Bottom left -1f, -1f, // Bottom left
@ -44,15 +47,26 @@ class TiltShiftRenderer(
1f, 1f // Top right 1f, 1f // Top right
) )
// Texture coordinates rotated 90° for portrait mode // Texture coordinates rotated 90° for portrait mode (back camera)
// (Camera sensors are landscape-oriented, we rotate to portrait) // (Camera sensors are landscape-oriented, we rotate to portrait)
private val texCoords = floatArrayOf( private val texCoordsBack = floatArrayOf(
1f, 1f, // Bottom left of screen -> bottom right of texture 1f, 1f, // Bottom left of screen -> bottom right of texture
1f, 0f, // Bottom right of screen -> top right of texture 1f, 0f, // Bottom right of screen -> top right of texture
0f, 1f, // Top left of screen -> bottom left of texture 0f, 1f, // Top left of screen -> bottom left of texture
0f, 0f // Top right of screen -> top left of texture 0f, 0f // Top right of screen -> top left of texture
) )
// Texture coordinates for front camera (mirrored + rotated)
// Front camera needs horizontal mirror for natural selfie view
private val texCoordsFront = floatArrayOf(
0f, 1f, // Bottom left of screen
0f, 0f, // Bottom right of screen
1f, 1f, // Top left of screen
1f, 0f // Top right of screen
)
private var currentTexCoords = texCoordsBack
override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
GLES20.glClearColor(0f, 0f, 0f, 1f) GLES20.glClearColor(0f, 0f, 0f, 1f)
@ -68,10 +82,10 @@ class TiltShiftRenderer(
vertexBuffer.position(0) vertexBuffer.position(0)
// Create texture coordinate buffer // Create texture coordinate buffer
texCoordBuffer = ByteBuffer.allocateDirect(texCoords.size * 4) texCoordBuffer = ByteBuffer.allocateDirect(currentTexCoords.size * 4)
.order(ByteOrder.nativeOrder()) .order(ByteOrder.nativeOrder())
.asFloatBuffer() .asFloatBuffer()
.put(texCoords) .put(currentTexCoords)
texCoordBuffer.position(0) texCoordBuffer.position(0)
// Create camera texture // Create camera texture
@ -101,6 +115,14 @@ class TiltShiftRenderer(
// Update texture with latest camera frame // Update texture with latest camera frame
surfaceTexture?.updateTexImage() surfaceTexture?.updateTexImage()
// Update texture coordinate buffer if camera changed
if (updateTexCoordBuffer) {
texCoordBuffer.clear()
texCoordBuffer.put(currentTexCoords)
texCoordBuffer.position(0)
updateTexCoordBuffer = false
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
// Use shader and set parameters // Use shader and set parameters
@ -143,6 +165,22 @@ class TiltShiftRenderer(
blurParameters = params blurParameters = params
} }
/**
* Sets whether using front camera. Updates texture coordinates accordingly.
* Thread-safe - actual buffer update happens on next frame.
*/
fun setFrontCamera(front: Boolean) {
if (isFrontCamera != front) {
isFrontCamera = front
currentTexCoords = if (front) texCoordsFront else texCoordsBack
// Buffer will be updated on next draw
updateTexCoordBuffer = true
}
}
@Volatile
private var updateTexCoordBuffer = false
/** /**
* Releases OpenGL resources. * Releases OpenGL resources.
* Must be called from GL thread. * Must be called from GL thread.

View file

@ -125,6 +125,12 @@ fun CameraScreen(
glSurfaceView?.requestRender() glSurfaceView?.requestRender()
} }
// Update renderer when camera switches (front/back)
LaunchedEffect(isFrontCamera) {
renderer?.setFrontCamera(isFrontCamera)
glSurfaceView?.requestRender()
}
// Start camera when surface texture is available // Start camera when surface texture is available
LaunchedEffect(surfaceTexture) { LaunchedEffect(surfaceTexture) {
surfaceTexture?.let { surfaceTexture?.let {