Skip to content

[Sample] [Graphics] UltraHDR x OpenGL shaders with SurfaceView brightness control #131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ constraintlayout = "2.1.4"
# Core dependencies
android-gradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "agp" }

androidx-activity = "androidx.activity:activity:1.8.1"
androidx-activity = "androidx.activity:activity:1.8.2"
androidx-core = "androidx.core:core-ktx:1.12.0"
androidx-appcompat = "androidx.appcompat:appcompat:1.6.1"
androidx-exifinterface = "androidx.exifinterface:exifinterface:1.3.6"
androidx-exifinterface = "androidx.exifinterface:exifinterface:1.3.7"
# Fragment 1.7.0 alpha and Transition 1.5.0 alpha are required for predictive back to work with Fragments and transitions
androidx-fragment = "androidx.fragment:fragment-ktx:1.7.0-alpha07"
androidx-transition = "androidx.transition:transition-ktx:1.5.0-alpha05"
androidx-activity-compose = "androidx.activity:activity-compose:1.8.1"
androidx-activity-compose = "androidx.activity:activity-compose:1.8.2"
androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment", version.ref = "androidx-navigation" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
androidx-navigation-testing = { module = "androidx.navigation:navigation-testing", version.ref = "androidx-navigation" }
Expand Down Expand Up @@ -125,6 +125,7 @@ androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.9.0"
androidx-core-remoteviews = "androidx.core:core-remoteviews:1.0.0"
androidx-glance-appwidget = "androidx.glance:glance-appwidget:1.0.0"
androidx-glance-material3 = "androidx.glance:glance-material3:1.0.0"
androidx-graphics-core = { group = "androidx.graphics", name = "graphics-core", version = "1.0.0-beta01" }
androidx-startup = 'androidx.startup:startup-runtime:1.1.1'
androidx-window = { module = "androidx.window:window", version.ref = "androidx-window" }
androidx-window-java = { module = "androidx.window:window-java", version.ref = "androidx-window" }
Expand Down
8 changes: 5 additions & 3 deletions samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ A sample showcasing how to handle calls with the Jetpack Telecom API
- [TextSpan](user-interface/text/src/main/java/com/example/platform/ui/text/TextSpan.kt):
buildSpannedString is useful for quickly building a rich text.
- [UltraHDR Image Capture](camera/camera2/src/main/java/com/example/platform/camera/imagecapture/Camera2UltraHDRCapture.kt):
This sample demonstrates how to capture a 10-bit compressed Ultra HDR still image.
This sample demonstrates how to capture a 10-bit compressed still image and
- [UltraHDR to HDR Video](media/ultrahdr/src/main/java/com/example/platform/media/ultrahdr/video/UltraHDRToHDRVideo.kt):
This sample demonstrates converting a series of Ultra HDR still images into an HDR video.
This sample demonstrates converting a series of UltraHDR images into a HDR
- [UltraHDR x OpenGLES SurfaceView](graphics/ultrahdr/src/main/java/com/example/platform/graphics/ultrahdr/opengl/UltraHDRWithOpenGL.kt):
This sample demonstrates displaying an UltraHDR image via and OpenGL Pipeline
- [Visualizing an UltraHDR Gainmap](graphics/ultrahdr/src/main/java/com/example/platform/graphics/ultrahdr/display/VisualizingAnUltraHDRGainmap.kt):
This sample demonstrates visualizing the underlying gainmap of an Ultra HDR image.
This sample demonstrates visualizing the underlying gainmap of an UltraHDR
- [WindowInsetsAnimation](user-interface/window-insets/src/main/java/com/example/platform/ui/insets/WindowInsetsAnimation.kt):
Shows how to react to the on-screen keyboard (IME) changing visibility, and also controlling the IME's visibility.
- [WindowManager](user-interface/windowmanager/src/main/java/com/example/platform/ui/windowmanager/demos/WindowDemosActivity.kt):
Expand Down
4 changes: 3 additions & 1 deletion samples/graphics/ultrahdr/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/*
* Copyright 2023 The Android Open Source Project
*
Expand Down Expand Up @@ -32,4 +31,7 @@ dependencies {
// Fresco
implementation(libs.fresco)
implementation(libs.fresco.nativeimagetranscoder)

// Graphics Core
implementation(libs.androidx.graphics.core)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// This fragment shader performs tone mapping by converting HDR image data into SDR format
// using a combination of transfer functions, Gainmap adjustments, exposure and gamma
// correction factors, and epsilon values for numerical stability.
precision mediump float;
varying vec2 vTextureCoord;

uniform highp float srcTF[7];
uniform highp mat3 gamutTransform;
uniform highp float destTF[7];
uniform sampler2D base;
uniform sampler2D gainmap;
uniform mediump vec3 logRatioMin;
uniform mediump vec3 logRatioMax;
uniform mediump vec3 gainmapGamma;
uniform mediump vec3 epsilonSdr;
uniform mediump vec3 epsilonHdr;
uniform mediump float W;
uniform highp int gainmapIsAlpha;
uniform highp int singleChannel;
uniform highp int noGamma;

highp float fromSrc(highp float x) {
highp float G = srcTF[0];
highp float A = srcTF[1];
highp float B = srcTF[2];
highp float C = srcTF[3];
highp float D = srcTF[4];
highp float E = srcTF[5];
highp float F = srcTF[6];
highp float s = sign(x);
x = abs(x);
x = x < D ? C * x + F : pow(A * x + B, G) + E;
return s * x;
}

highp float toDest(highp float x) {
highp float G = destTF[0];
highp float A = destTF[1];
highp float B = destTF[2];
highp float C = destTF[3];
highp float D = destTF[4];
highp float E = destTF[5];
highp float F = destTF[6];
highp float s = sign(x);
x = abs(x);
x = x < D ? C * x + F : pow(A * x + B, G) + E;
return s * x;
}

highp vec4 sampleBase(vec2 coord) {
vec4 color = texture2D(base, vTextureCoord);
color = vec4(color.xyz / max(color.w, 0.0001), color.w);
color.x = fromSrc(color.x);
color.y = fromSrc(color.y);
color.z = fromSrc(color.z);
color.xyz *= color.w;
return color;
}

void main() {
vec4 S = sampleBase(vTextureCoord);
vec4 G = texture2D(gainmap, vTextureCoord);
vec3 H;

if (gainmapIsAlpha == 1) {
G = vec4(G.w, G.w, G.w, 1.0);
mediump float L;

if (noGamma == 1) {
L = mix(logRatioMin.x, logRatioMax.x, G.x);
} else {
L = mix(logRatioMin.x, logRatioMax.x, pow(G.x, gainmapGamma.x));
}

H = (S.xyz + epsilonSdr) * exp(L * W) - epsilonHdr;
} else {
mediump vec3 L;
if (noGamma == 1) {
L = mix(logRatioMin, logRatioMax, G.xyz);
} else {
L = mix(logRatioMin, logRatioMax, pow(G.xyz, gainmapGamma));
}

H = (S.xyz + epsilonSdr) * exp(L * W) - epsilonHdr;
}

vec4 result = vec4(H.xyz / max(S.w, 0.0001), S.w);
result.rgb = (gamutTransform * result.rgb);
result.x = toDest(result.x);
result.y = toDest(result.y);
result.z = toDest(result.z);
result.xyz *= result.w;

gl_FragColor = result;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// This vertex shader program transforms vertices from object space to clip space and
// prepares texture coordinates for fragment shader processing in a fragment shader.
//
// refer to fs_uhdr_tonemapper.frag
//
uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec2 aTextureCoord;
varying vec2 vTextureCoord;

void main() {
gl_Position = uMVPMatrix * aPosition;
vTextureCoord = aTextureCoord;
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,19 @@ class ColorModeControls : LinearLayout, WindowObserver {

binding.ultrahdrColorModeCurrentMode.run {
val mode = when (it.colorMode) {
ActivityInfo.COLOR_MODE_DEFAULT -> resources.getString(R.string.color_mode_sdr)
ActivityInfo.COLOR_MODE_DEFAULT -> String.format(
resources.getString(R.string.color_mode_sdr_with_ratio),
sdrHdrRatio,
)

ActivityInfo.COLOR_MODE_HDR -> String.format(
resources.getString(R.string.color_mode_hdr_with_ratio),
sdrHdrRatio,
)

else -> resources.getString(R.string.color_mode_unknown)
}
text = "Activity Color Mode: " + mode
text = mode
}
}
}
Expand Down
Loading