Fix front camera rotation mirroring in shader
Add uIsFrontCamera uniform to shader and adjust coordinate transformations for front camera's mirrored texture coordinates: - Position transform: (1-posY, 1-posX) instead of (posY, 1-posX) - Angle transform: -angle - 90° instead of +angle + 90° Applied to linearFocusDistance, radialFocusDistance, and blur direction calculations in sampleBlurred. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b16dd971f2
commit
0cd41e9814
3 changed files with 51 additions and 17 deletions
|
|
@ -126,7 +126,7 @@ class TiltShiftRenderer(
|
|||
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
|
||||
|
||||
// Use shader and set parameters
|
||||
shader.use(cameraTextureId, blurParameters, surfaceWidth, surfaceHeight)
|
||||
shader.use(cameraTextureId, blurParameters, surfaceWidth, surfaceHeight, isFrontCamera)
|
||||
|
||||
// Set vertex positions
|
||||
GLES20.glEnableVertexAttribArray(shader.aPositionLocation)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class TiltShiftShader(private val context: Context) {
|
|||
// Uniform locations
|
||||
private var uTextureLocation: Int = 0
|
||||
private var uModeLocation: Int = 0
|
||||
private var uIsFrontCameraLocation: Int = 0
|
||||
private var uAngleLocation: Int = 0
|
||||
private var uPositionXLocation: Int = 0
|
||||
private var uPositionYLocation: Int = 0
|
||||
|
|
@ -65,6 +66,7 @@ class TiltShiftShader(private val context: Context) {
|
|||
// Get uniform locations
|
||||
uTextureLocation = GLES20.glGetUniformLocation(programId, "uTexture")
|
||||
uModeLocation = GLES20.glGetUniformLocation(programId, "uMode")
|
||||
uIsFrontCameraLocation = GLES20.glGetUniformLocation(programId, "uIsFrontCamera")
|
||||
uAngleLocation = GLES20.glGetUniformLocation(programId, "uAngle")
|
||||
uPositionXLocation = GLES20.glGetUniformLocation(programId, "uPositionX")
|
||||
uPositionYLocation = GLES20.glGetUniformLocation(programId, "uPositionY")
|
||||
|
|
@ -82,7 +84,7 @@ class TiltShiftShader(private val context: Context) {
|
|||
/**
|
||||
* Uses the shader program and sets uniforms.
|
||||
*/
|
||||
fun use(textureId: Int, params: BlurParameters, width: Int, height: Int) {
|
||||
fun use(textureId: Int, params: BlurParameters, width: Int, height: Int, isFrontCamera: Boolean = false) {
|
||||
GLES20.glUseProgram(programId)
|
||||
|
||||
// Bind camera texture
|
||||
|
|
@ -92,6 +94,7 @@ class TiltShiftShader(private val context: Context) {
|
|||
|
||||
// Set effect parameters
|
||||
GLES20.glUniform1i(uModeLocation, if (params.mode == BlurMode.RADIAL) 1 else 0)
|
||||
GLES20.glUniform1i(uIsFrontCameraLocation, if (isFrontCamera) 1 else 0)
|
||||
GLES20.glUniform1f(uAngleLocation, params.angle)
|
||||
GLES20.glUniform1f(uPositionXLocation, params.positionX)
|
||||
GLES20.glUniform1f(uPositionYLocation, params.positionY)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ uniform samplerExternalOES uTexture;
|
|||
|
||||
// Effect parameters
|
||||
uniform int uMode; // 0 = linear, 1 = radial
|
||||
uniform int uIsFrontCamera; // 0 = back camera, 1 = front camera
|
||||
uniform float uAngle; // Rotation angle in radians
|
||||
uniform float uPositionX; // Horizontal center of focus (0-1)
|
||||
uniform float uPositionY; // Vertical center of focus (0-1)
|
||||
|
|
@ -24,9 +25,15 @@ varying vec2 vTexCoord;
|
|||
// Calculate signed distance from the focus region for LINEAR mode
|
||||
float linearFocusDistance(vec2 uv) {
|
||||
// Center point of the focus region
|
||||
// Transform from screen coordinates to texture coordinates (90° rotation)
|
||||
// Screen (x,y) -> Texture (y, 1-x)
|
||||
vec2 center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
// Transform from screen coordinates to texture coordinates
|
||||
// Back camera: Screen (x,y) -> Texture (y, 1-x)
|
||||
// Front camera: Screen (x,y) -> Texture (1-y, 1-x) (additional X flip for mirror)
|
||||
vec2 center;
|
||||
if (uIsFrontCamera == 1) {
|
||||
center = vec2(1.0 - uPositionY, 1.0 - uPositionX);
|
||||
} else {
|
||||
center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
}
|
||||
vec2 offset = uv - center;
|
||||
|
||||
// Correct for screen aspect ratio to make coordinate space square
|
||||
|
|
@ -35,9 +42,15 @@ float linearFocusDistance(vec2 uv) {
|
|||
float screenAspect = uResolution.x / uResolution.y;
|
||||
offset.y *= screenAspect;
|
||||
|
||||
// Adjust angle by +90 degrees to compensate for the coordinate transformation
|
||||
// The position transform is a 90° CW rotation, so angles transform as θ + 90°
|
||||
float adjustedAngle = uAngle + 1.5707963;
|
||||
// Adjust angle to compensate for the coordinate transformation
|
||||
// Back camera: +90° for the 90° CW rotation
|
||||
// Front camera: -90° (negated due to X flip mirror effect)
|
||||
float adjustedAngle;
|
||||
if (uIsFrontCamera == 1) {
|
||||
adjustedAngle = -uAngle - 1.5707963;
|
||||
} else {
|
||||
adjustedAngle = uAngle + 1.5707963;
|
||||
}
|
||||
float cosA = cos(adjustedAngle);
|
||||
float sinA = sin(adjustedAngle);
|
||||
|
||||
|
|
@ -50,9 +63,13 @@ float linearFocusDistance(vec2 uv) {
|
|||
// Calculate signed distance from the focus region for RADIAL mode
|
||||
float radialFocusDistance(vec2 uv) {
|
||||
// Center point of the focus region
|
||||
// Transform from screen coordinates to texture coordinates (90° rotation)
|
||||
// Screen (x,y) -> Texture (y, 1-x)
|
||||
vec2 center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
// Transform from screen coordinates to texture coordinates
|
||||
vec2 center;
|
||||
if (uIsFrontCamera == 1) {
|
||||
center = vec2(1.0 - uPositionY, 1.0 - uPositionX);
|
||||
} else {
|
||||
center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
}
|
||||
vec2 offset = uv - center;
|
||||
|
||||
// Correct for screen aspect ratio to make coordinate space square
|
||||
|
|
@ -61,9 +78,13 @@ float radialFocusDistance(vec2 uv) {
|
|||
float screenAspect = uResolution.x / uResolution.y;
|
||||
offset.y *= screenAspect;
|
||||
|
||||
// Apply rotation
|
||||
// Adjust angle by +90 degrees to compensate for the coordinate transformation
|
||||
float adjustedAngle = uAngle + 1.5707963;
|
||||
// Apply rotation with angle adjustment for coordinate transformation
|
||||
float adjustedAngle;
|
||||
if (uIsFrontCamera == 1) {
|
||||
adjustedAngle = -uAngle - 1.5707963;
|
||||
} else {
|
||||
adjustedAngle = uAngle + 1.5707963;
|
||||
}
|
||||
float cosA = cos(adjustedAngle);
|
||||
float sinA = sin(adjustedAngle);
|
||||
vec2 rotated = vec2(
|
||||
|
|
@ -120,8 +141,13 @@ vec4 sampleBlurred(vec2 uv, float blur) {
|
|||
vec2 blurDir;
|
||||
if (uMode == 1) {
|
||||
// Radial: blur away from center
|
||||
// Transform from screen coordinates to texture coordinates (90° rotation)
|
||||
vec2 center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
// Transform from screen coordinates to texture coordinates
|
||||
vec2 center;
|
||||
if (uIsFrontCamera == 1) {
|
||||
center = vec2(1.0 - uPositionY, 1.0 - uPositionX);
|
||||
} else {
|
||||
center = vec2(uPositionY, 1.0 - uPositionX);
|
||||
}
|
||||
vec2 toCenter = uv - center;
|
||||
float len = length(toCenter);
|
||||
if (len > 0.001) {
|
||||
|
|
@ -132,7 +158,12 @@ vec4 sampleBlurred(vec2 uv, float blur) {
|
|||
} else {
|
||||
// Linear: blur perpendicular to focus line
|
||||
// Adjust angle for coordinate transformation
|
||||
float blurAngle = uAngle + 1.5707963;
|
||||
float blurAngle;
|
||||
if (uIsFrontCamera == 1) {
|
||||
blurAngle = -uAngle - 1.5707963;
|
||||
} else {
|
||||
blurAngle = uAngle + 1.5707963;
|
||||
}
|
||||
blurDir = vec2(cos(blurAngle), sin(blurAngle));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue