이 페이지에서

Qt Quick 3D - 하늘 머티리얼 예시

SkyMaterial 를 사용하여 절차적 하늘 렌더링과 이미지 기반 조명(IBL)을 시연합니다.

주변 환경을 반사하는 PBR 구체를 활용한 절차적 분위기 하늘

이 예제는 ` SkyMaterial `를 사용하여 절차적 하늘을 렌더링하고, 그 결과로 생성된 큐브맵을 씬의 PBR 머티리얼에 대한 이미지 기반 라이팅(IBL)의 라이트 프로브로 활용하는 방법을 보여줍니다.

AdvancedSky 헬퍼는 SkyMaterial 의 서브클래스로, Hillaire의 "A Scalable and Production Ready Sky and Atmosphere Rendering Technique"(2020)에 따른 물리 기반 대기 산란 모델을 구현하며, 에어로졸, 오존, 시선 고도 및 레이 마칭 방식의 볼륨 구름을 구성할 수 있습니다.

씬 설정

이 애플리케이션은 ApplicationWindow 를 사용하며, View3D 가 창 전체를 채웁니다. 설정 패널은 왼쪽 가장자리에 오버레이되어 있으며, 토글 버튼을 클릭하면 슬라이드 방식으로 나타나거나 사라집니다. 관련 QtQuick3D 임포트는 다음과 같습니다:

import QtQuick
import QtQuick.Controls

import QtQuick3D
import QtQuick3D.Helpers

하늘 머티리얼 정의

AdvancedSky 는 View3D 내부에서 선언되므로, 동일한 skyLight Node (태양)을 공유합니다:

AdvancedSky {
    id: advancedSky
    skyLight: sun
}

AdvancedSky 는 AdvancedSky.qml 에 정의된 SkyMaterial 의 서브클래스입니다. 이 클래스의 QML 속성은 자동으로 유니폼(uniforms)으로 프래그먼트 셰이더에 전달됩니다.

이미지 기반 조명

SceneEnvironment::skyMaterial 에 스카이 머티리얼을 할당하면, 절차적으로 렌더링된 큐브맵이 가시적인 배경으로 사용될 뿐만 아니라, 씬 내 PBR 머티리얼에 대한 이미지 기반 라이팅의 소스로도 사용됩니다:

environment: SceneEnvironment {
    backgroundMode: SceneEnvironment.SkyMaterial
    skyMaterial: advancedSky
    probeExposure: 0.25
    tonemapMode: SceneEnvironment.TonemapModeAces
}

데모에서 가장 매끄러운 구체는 절차적 하늘을 거의 완벽하게 반사하며, 표면이 거친 구체들은 절차적 큐브맵 위에 SkyMaterial 의 GGX 프리필터 체인이 적용되어 점차 흐릿해지는 반사 효과를 보여줍니다.

하늘 렌더링 방식 선택

skyboxMode 이 옵션은 반사에 사용되는 IBL 큐브와 독립적으로, SkyMaterial 가 보이는 배경으로 생성할 내용을 선택합니다:

  • SkyMaterial.Cubemap 라디언스 큐브맵(이미지 기반 조명에 사용되는 것과 동일한 큐브)을 샘플링하므로, 정적 하늘의 경우 큐브는 한 번만 렌더링된 후 매 프레임마다 낮은 비용으로 샘플링됩니다. 배경의 선명도는 ‘ radianceMapSize ’로 제한됩니다. 이는 카메라만 움직일 때 프레임당 비용이 가장 낮은 방식입니다.
  • ScreenSpace 모드는 매 프레임마다 화면에서 직접 스카이 셰이더를 평가하며, 축당 전체, 절반 또는 1/4 해상도로 처리됩니다. 이 모드는 가시 배경을 IBL 큐브와 분리하여, 프레임당 렌더링 비용을 대가로 동적 조건(움직이는 태양, 애니메이션된 볼륨 클라우드)에서도 선명한 하늘을 제공합니다. 스케일을 낮출수록 선명도는 떨어지지만 속도는 빨라집니다.

설정 패널의 “스카이박스 모드(Skybox mode)” 콤보 박스를 전환하여 옵션을 실시간으로 비교해 보세요. 큐브맵 모드는 비용 효율적이지만 태양과 구름이 움직일수록 이미지가 흐려지는 반면, 스크린 스페이스 모드는 모든 변화를 선명하게 추적합니다.

프레임 예산 관리

iblRenderFrames IBL 프리필터를 여러 프레임에 분산합니다. 즉, 총 iblSampleCount 값을 수렴할 때까지 프레임당 한 조각씩 점진적으로 통합합니다. 기본값인 0 는 샘플 누적, 정규화, 조도 계산을 모두 단일 프레임 내에서 수행합니다. 이 값을 높이면 프리필터 비용을 분산시켜, IBL 샘플 수가 많을 때도 장면의 반응성을 유지할 수 있습니다.

태양 애니메이션

"태양 애니메이션(Animate sun)" 토글이 켜져 있으면, 태양 위치( FrameAnimation )가 지평선을 따라 앞뒤로 이동합니다. 태양 위치가 변경될 때마다 IBL 누적기가 무효화되지만, 태양 위치 업데이트 간격( iblRenderFrames )을 적절히 설정하면 사전 필터링 비용이 여러 프레임에 분산되어, 단일 프레임에서 전체 비용을 부담하는 일이 없습니다.

FrameAnimation {
    id: sunAnimator
    running: settingsPane.animateSun

    property real t: 0
    property real lastT: 0
    property int direction: 1

    onTriggered: {
        const min = -180
        const max = 0
        lastT = t
        t += direction * frameTime * settingsPane.sunSweepSpeed
        sun.eulerRotation.x = min + (Math.sin(t) * 0.5 + 0.5) * (max - min)
    }

    function updatePhaseFromSun() {
        const min = -180
        const max = 0
        let norm = Math.max(0.0, Math.min(1.0, (sun.eulerRotation.x - min) / (max - min)))
        t = Math.asin(norm * 2.0 - 1.0)
        direction = lastT < t ? 1 : -1
    }
}

설정 패널

설정 패널은 뷰포트 왼쪽 상단 모서리의 버튼을 통해 토글되며, View3D 위로 슬라이드되어 나타나거나 사라집니다. 이 패널은 두 그룹으로 나뉩니다.

하늘

하늘의 외관과 구름을 제어하는 항목입니다.

  • 태양 애니메이션 — 수평선을 가로질러 탁구공처럼 왔다 갔다 하는 태양 스윕을 실행합니다.
  • 순환 속도 — 태양 애니메이션의 이동 속도입니다.
  • 태양 고도 — 도 단위로 표시되는 수동 태양 위치(0° = 새벽, 90° = 정오, 180° = 해질녘).
  • 구름 활성화 — 레이 마칭 방식의 볼륨 구름을 표시하거나 숨깁니다.
  • 구름 덮임 — 구름으로 덮인 하늘의 비율 (0 = 맑음, 1 = 흐림).
  • 바람 애니메이션 — 매 프레임마다 구름 노이즈 텍스처를 이동시켜 IBL 누적기를 지속적으로 무효화합니다. 프레임 예산 제어를 위한 유용한 스트레스 테스트입니다.
렌더링

SkyMaterial 기본 클래스 속성에 직접 매핑되는 컨트롤입니다.

카메라는 표준 WasdController 내비게이션에 반응합니다 — W/A/S/D 키와 마우스 드래그를 사용하여 주위를 둘러볼 수 있습니다. 뷰포트를 탭하면 키보드 포커스가 해당 영역으로 이동합니다.

예제 프로젝트 @ code.qt.io

SkyMaterial 및 SceneEnvironment도 참조하십시오 .

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.