Skip to content

Commit

Permalink
[Sample] [Graphics] UltraHDR x OpenGL shaders with SurfaceView bright…
Browse files Browse the repository at this point in the history
…ness control (#131)

* UltraHDR with OpenGL graphics pipeline initial implementation

* Rename files to be consistent

* Updates to GL Shader Logic + GL Library Logic

* Update fragment implementation to control extended range brightness

* Added copyright docs

* Fixes after merge
  • Loading branch information
madebymozart authored Dec 18, 2023
1 parent a30a043 commit 3856087
Show file tree
Hide file tree
Showing 10 changed files with 1,022 additions and 10 deletions.
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

0 comments on commit 3856087

Please sign in to comment.