WWDC Quick Look 💓 By SwiftGGTeam
Explore HDR rendering with EDR

Explore HDR rendering with EDR

元の動画を見る

ハイライト

EDR により、アプリは HDR 対応ディスプレイで SDR 範囲(>1.0)を超える輝度値を出力できる。システムはディスプレイ能力に応じて tone mapping を自動的に行い、Pro Display XDR では最大で約 6 倍の SDR 輝度に達する。

主な内容

レンダリングエンジンは 0-1 の範囲でカラー値を出力している。SDR ディスプレイでは問題ないが、HDR ディスプレイではハードウェア能力を活かしきれていない。Pro Display XDR は SDR の 6 倍明るいピクセルを表示でき、MacBook Pro は 2-3 倍の明るさを表示できる。この追加のダイナミックレンジをどう活用すればよいだろうか。

EDR(Extended Dynamic Range)は Apple の解決策だ。色管理に似ているが、管理するのは輝度範囲である。

詳細

EDR とは何か

00:50

EDR は同時に 2 つのものを指す。

  1. HDR 表現形式:カラー値が 1.0 を超えることを許可する
  2. HDR レンダリング技術:システムがディスプレイ能力に応じて自動的にマッピングする

SDR システムでは、白は 1.0 と定義される。EDR でも 1.0 は SDR の白のままだが、1.0 を超える値を許可する。表示時にはシステムが自動的に判断し、HDR 画面ではより明るいピクセルを直接表示し、SDR 画面では tone mapping によって 1.0 の範囲へ圧縮する。

02:30

キーポイント:

  • SDR の白 = 1.0
  • EDR は値 > 1.0 を許可する
  • システムが HDR と SDR ディスプレイのマッピングを自動処理する
  • EDR の上限はディスプレイごとに異なる

4 ステップで EDR サポートを追加する

03:37

Apple は 4 ステップで EDR を追加することを推奨している。

  1. EDR サポートを検出する
  2. レンダーターゲットを設定する
  3. shader で HDR 値を出力する
  4. tone mapping を処理する

EDR サポートを検出する

05:00

// 画面が EDR をサポートしているか確認する
let screen = window.screen
let maxEDR = screen.maximumExtendedDynamicRangeColorComponentValue

if maxEDR > 1.0 {
    // EDR をサポートしている
    print("EDR max: \(maxEDR)")  // Pro Display XDR では約 6.0
}

05:00

キーポイント:

  • maximumExtendedDynamicRangeColorComponentValue は EDR の上限を返す
  • 1.0 は EDR 非対応を示す
  • 値が大きいほど、ディスプレイの HDR 能力が高い
  • 画面ごとに異なる値になる場合がある

CAMetalLayer を設定する

17:52

// Metal layer を EDR 対応に設定する
metalLayer.wantsExtendedDynamicRangeContent = true
metalLayer.pixelFormat = .rgba16Float  // 16-bit float 形式

// colorspace を設定する
if let edrColorSpace = CGColorSpace(name: CGColorSpace.displayP3_PQ) {
    metalLayer.colorspace = edrColorSpace
}

18:53

キーポイント:

  • wantsExtendedDynamicRangeContent = true で EDR を有効にする
  • 16-bit float pixel format(.rgba16Float)を使用する
  • HDR 対応の color space(例:Display P3 PQ)を選ぶ
  • 最大限の EDR 能力を発揮するには、フルスクリーンまたは独立ウィンドウが必要

Shader で HDR 値を出力する

20:30

fragment float4 hdrFragment(...) {
    // シーンのレンダリング
    float3 sceneColor = computeLighting(...);

    // シーン値は 1.0 を超える場合がある
    // たとえば太陽の反射は 4.0 以上に達することがある

    // そのまま出力し、EDR システムにマッピングを任せる
    return float4(sceneColor, 1.0);
}

21:00

キーポイント:

  • 1.0 を超える値をそのまま出力する
  • 手動で clamp する必要はない
  • EDR システムがディスプレイ能力に応じて自動的にマッピングする
  • 線形空間を維持し、gamma 補正は行わない

Tone Mapping

22:30

SDR ディスプレイでは、システムが tone mapping を自動的に行う。ただし、マッピング曲線を自分で制御したい場合は shader 内で実装できる。

float3 toneMap(float3 hdrColor, float maxEDR) {
    // シンプルな Reinhard tone mapping
    float3 mapped = hdrColor / (1.0 + hdrColor);

    // または ACES filmic tone mapping を使用
    // mapped = ACESFilm(hdrColor);

    return mapped;
}

23:30

キーポイント:

  • システムが SDR ディスプレイ向けのマッピングを自動処理する
  • カスタム tone mapping は特定のスタイルが必要な場合だけ使う
  • 最後のステップまで線形空間を維持する
  • シーンによって異なる tone mapping 曲線が必要になることがある

EDR と AVPlayer

16:00

AVPlayer は EDR を自動的にサポートする。HDR コンテンツを再生するとき、ディスプレイの EDR 能力を自動的に活用する。

let player = AVPlayer(url: hdrVideoURL)
let playerLayer = AVPlayerLayer(player: player)

// AVPlayer は EDR を自動処理するため、追加設定は不要
playerLayer.videoGravity = .resizeAspect

16:00

キーポイント:

  • AVPlayer は HDR コンテンツを自動検出する
  • EDR の表示能力を自動的に活用する
  • 手動設定は不要
  • SDR ディスプレイでは自動的に tone mapping する

重要ポイント

  1. ゲームに HDR ハイライト効果を追加する。太陽、爆発、ネオンライトなどの光源は 2-6 倍の SDR 輝度を出力できる。主な API:metalLayer.wantsExtendedDynamicRangeContent = true

  2. 16-bit float render target を使う。HDR コンテンツには十分な精度が必要で、8-bit では足りない。主な API:pixelFormat = .rgba16Float

  3. ディスプレイの EDR 能力を検出してコンテンツを調整する。EDR の上限はディスプレイごとに異なるため、能力に応じて HDR コンテンツの強度を調整する。主な API:screen.maximumExtendedDynamicRangeColorComponentValue

  4. SDR と HDR の両方のディスプレイで効果をテストする。システムは自動的に tone mapping するが、結果は異なる場合がある。両方のディスプレイで良好な見た目になることを確認する。

  5. プロ向け動画アプリに EDR ワークフローを設定する。Display P3 PQ color space + 16-bit float + EDR の有効化を組み合わせる。主な API:CGColorSpace.displayP3_PQ

関連セッション

コメント

GitHub Issues · utterances