Qt Quick 3D - 사용자 패스 예제
Qt Quick 3D 에서 사용자 정의 렌더 패스를 생성하는 방법을 보여줍니다.

}
'사용자 패스' 예제는 Qt Quick 3D 에서 사용자 정의 렌더 패스를 생성하는 방법을 보여줍니다. 이 예제는 여러 사용자 정의 렌더 패스를 사용하여 지연 조명(deferred lighting) 렌더링 파이프라인을 구현하며, 불투명 지오메트리, 스카이박스, 씬에 삽입된 2D 아이템, 투명 지오메트리 등 전체 렌더링 순서를 처리하는 방법을 보여줍니다.
내부 렌더 패스 비활성화
기본적으로 Qt Quick 3D 는 3D 장면을 렌더링하기 위해 일련의 내부 렌더 패스를 사용합니다. 경우에 따라 이러한 내부 패스를 비활성화하고 사용자 정의 렌더 패스를 사용하여 자체 렌더링 파이프라인을 구현하고 싶을 수 있습니다.
내부 렌더 패스를 비활성화하려면, ` View3D `의 ` renderOverrides ` 속성을 ` View3D.DisableInternalPasses`로 설정하십시오.
View3D {
id: view3D
anchors.fill: parent
renderOverrides: View3D.DisableInternalPasses
environment: ExtendedSceneEnvironment {
lightProbe: Texture {
textureData: ProceduralSkyTextureData {
}
}
backgroundMode: SceneEnvironment.SkyBox
}내부 렌더링 패스를 비활성화하면, 화면에 무언가를 표시하기 위해 ` View3D `에 메인 컬러 패스의 결과를 제공해야 합니다.
지오메트리 버퍼 패스
이 예제에서 첫 번째 사용자 정의 렌더 패스는 장면의 지오메트리를 여러 렌더 타깃에 렌더링하고, 각 타깃에 서로 다른 머티리얼 속성을 저장하는 지오메트리 버퍼(G-버퍼) 패스입니다. 제공된 예제는 Qt Quick 3D 머티리얼이 제공하는 전체 머티리얼 속성의 일부로, 기본적인 디퍼드 라이팅 구현에 필요한 속성에 중점을 두고 있습니다.
당사의 RenderPass 는 GBufferPass.qml 에 정의되어 있습니다:
RenderPass {
id: gbufferPass
clearColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
property alias layerMask: filter.layerMask
required property RenderPassTexture depthTexture
RenderPassTexture {
id: gbuffer0
format: RenderPassTexture.RGBA16F
// rgb: baseColor (linear), a: metalness
}
RenderPassTexture {
id: gbuffer1
format: RenderPassTexture.RGBA16F
// rgb: normal, a: roughness
}
RenderPassTexture {
id: gbuffer2
format: RenderPassTexture.RGBA16F
// rgb: emissive, a: ao/spare
}
commands: [
ColorAttachment { target: gbuffer0; name: "GBUFFER0" },
ColorAttachment { target: gbuffer1; name: "GBUFFER1" },
ColorAttachment { target: gbuffer2; name: "GBUFFER2" },
DepthTextureAttachment { target: gbufferPass.depthTexture },
RenderablesFilter {
id: filter
renderableTypes: RenderablesFilter.Opaque
}
]
materialMode: RenderPass.AugmentMaterial
augmentShader: "gbuffer_augment.glsl"
}이 RenderPassTexture 는 3개의 컬러 어태치먼트와 1개의 깊이 어태치먼트를 정의합니다. 이 패스는 RenderPass 내부에서 객체로 정의된 3개의 텍스처를 필요로 합니다. 이 3개의 RenderPassTextures는 패스의 컬러 어태치먼트에 대한 타깃으로 사용되며, 깊이 어태치먼트는 패스 외부에서 제공되는 깊이 텍스처를 사용합니다.
RenderPass 자체는 AugmentMaterial 모드로 설정되어 있으며, 이는 렌더링되는 오브젝트의 머티리얼에 추가 셰이더 코드를 적용하여 보강함을 의미합니다. 보강 셰이더는 gbuffer_augment.glsl 파일에 제공되며, 이 파일은 필요한 머티리얼 속성을 여러 렌더 타깃으로 출력합니다.
void MAIN_FRAGMENT_AUGMENT()
{
vec3 baseColor = BASE_COLOR.rgb;
float metalness = METALNESS;
float roughness = ROUGHNESS;
vec3 worldNormal = normalize(WORLD_NORMAL);
// GBuffer 0: albedo + metalness
GBUFFER0 = vec4(baseColor, metalness);
// GBuffer 1: normal (encoded to 0..1) + roughness
GBUFFER1 = vec4(worldNormal * 0.5 + 0.5, roughness);
// GBuffer 2: world position
GBUFFER2 = vec4(qt_varWorldPos, 1.0);
}여기서는 베이스 컬러, 메탈니스, 월드 노멀, 러프니스 및 월드 위치가 G-버퍼의 3가지 컬러 어태치먼트에 어떻게 저장되는지 확인할 수 있습니다.
렌더링 파이프라인에서 G-버퍼 패스를 실제로 사용하려면, ` Main.qml`에서 해당 인스턴스를 생성하고 필요한 깊이 텍스처를 제공해야 합니다:
RenderPassTexture {
id: mainDepthStencilTexture
format: RenderPassTexture.Depth24Stencil8
}
GBufferPass {
id: gbufferPass
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
depthTexture: mainDepthStencilTexture
}
RenderOutputProvider {
id: gbuffer0Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment0
}
RenderOutputProvider {
id: gbuffer1Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment1
}
RenderOutputProvider {
id: gbuffer2Provider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: gbufferPass
attachmentSelector: RenderOutputProvider.Attachment2
}렌더링된 G-버퍼 텍스처에 대한 참조를 제공하기 위해 3개의 ` RenderOutputProvider ` 인스턴스가 생성되며, 이는 후속 라이팅 패스에서 사용됩니다.
G-버퍼 패스의 ` layerMask ` 속성은 ` ContentLayer.Layer0` 및 ` ContentLayer.Layer1`에 있는 오브젝트만 렌더링하도록 설정됩니다. 이를 통해 각 오브젝트의 ` layers ` 속성을 적절히 설정함으로써, G-버퍼 패스에서 렌더링될 오브젝트를 제어할 수 있습니다.
메인 컬러 패스 및 서브 렌더 패스
이 예제는 단일한 플랫 렌더 패스 대신, 메인 컬러 및 깊이 텍스처를 소유하고 SubRenderPass 자식 객체들의 시퀀스를 통해 모든 렌더링을 조율하는 복합 mainColorPass 을 사용합니다.
각 SubRenderPass 는 상위 패스와 동일한 렌더 타깃을 공유하며 순서대로 실행됩니다. 이를 통해 각 단계가 이전 단계의 결과에 더해지는 계층적 렌더링 파이프라인을 간단하게 구축할 수 있습니다.
RenderPass {
id: mainColorPass
clearColor: "black"
// Preserve depth across SubRenderPasses so geometry depth is available
// when rendering the skybox, transparent objects, and 2D items.
renderTargetFlags: RenderPass.RenderTargetFlags.PreserveDepthStencilContents
commands: [
ColorAttachment {
target: mainColorTexture
},
DepthTextureAttachment {
target: mainDepthStencilTexture
},
RenderablesFilter {
// Nothing renders directly in the outer pass; all rendering
// is delegated to the SubRenderPasses below.
renderableTypes: RenderablesFilter.None
},
// 1. Deferred lighting: shade opaque geometry stored in the G-buffer.
SubRenderPass {
renderPass: RenderPass {
id: deferredLightingPass
materialMode: RenderPass.OriginalMaterial
commands: [
PipelineStateOverride {
// The full-screen quad must not write or test depth;
// geometry depth was already written by the G-buffer pass.
depthWriteEnabled: false
depthTestEnabled: false
},
RenderablesFilter { layerMask: ContentLayer.Layer13 }
]
}
},
// 2. Skybox: render the environment behind all scene geometry.
SubRenderPass {
renderPass: RenderPass {
id: skyboxPass
passMode: RenderPass.SkyboxPass
commands: [
PipelineStateOverride {
// The skybox is rendered "at infinity" so it must
// depth-test (to be hidden by geometry) but must not
// write depth.
depthTestEnabled: true
depthWriteEnabled: false
}
]
}
},
// 3. 2D items: render any Qt Quick Items embedded in the 3D scene.
SubRenderPass {
renderPass: RenderPass {
id: item2DPass
passMode: RenderPass.Item2DPass
}
},
// 4. Transparent objects: render blended geometry on top of everything else.
SubRenderPass {
renderPass: RenderPass {
id: transparentItemPass
materialMode: RenderPass.OriginalMaterial
commands: [
RenderablesFilter {
renderableTypes: RenderablesFilter.Transparent
layerMask: ContentLayer.Layer0 | ContentLayer.Layer1
},
PipelineStateOverride {
// Enable alpha blending and depth testing so transparent
// objects sort correctly against opaque geometry.
blendEnabled: true
depthTestEnabled: true
targetBlend0.enable: true
targetBlend0.srcColor: RenderTargetBlend.SrcAlpha
targetBlend0.dstColor: RenderTargetBlend.OneMinusSrcAlpha
targetBlend0.srcAlpha: RenderTargetBlend.One
targetBlend0.dstAlpha: RenderTargetBlend.OneMinusSrcAlpha
}
]
}
}
]
}외부 패스는 ` renderableTypes: RenderablesFilter.None`을 설정하여 부모 패스에서 직접 렌더링되는 것이 없도록 하며, 모든 렌더링은 하위 패스로 위임됩니다. ` PreserveDepthStencilContents ` 플래그는 G-버퍼 패스가 기록한 깊이 값을 모든 하위 패스에서 사용할 수 있도록 보장합니다.
지연 조명 서브패스
첫 번째 서브패스는 지연 조명 계산을 수행합니다. 이 패스는 G-버퍼 텍스처를 샘플링하고 모든 픽셀에 대한 조명을 평가하는 전체 화면의 deferredLightingQuad 모델을 렌더링합니다.
Model {
id: deferredLightingQuad
layers: ContentLayer.Layer13
castsShadows: false
receivesShadows: false
geometry: PlaneGeometry {
// geometry doesn't matter, just need 4 verts
plane: PlaneGeometry.XY
}
materials: [
CustomMaterial {
id: lightingPassMaterial
property TextureInput gbuffer0: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer0Provider
}
}
property TextureInput gbuffer1: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer1Provider
}
}
property TextureInput gbuffer2: TextureInput {
enabled: true
texture: Texture {
textureProvider: gbuffer2Provider
}
}
shadingMode: CustomMaterial.Unshaded
fragmentShader: "lighting.frag"
vertexShader: "lighting.vert"
}
]
}deferredLightingQuad 는 G-버퍼 패스에서는 보이지 않고 이 서브패스에서만 렌더링되도록 ContentLayer.Layer13 에 배치됩니다.
PipelineStateOverride 는 쿼드에 대한 깊이 쓰기 및 깊이 테스트를 모두 비활성화합니다. G-버퍼 패스는 이미 씬 지오메트리에 대한 올바른 깊이를 기록했으므로, 전체 화면 쿼드는 깊이를 변경하거나 테스트해서는 안 됩니다.
스카이박스 서브패스
두 번째 서브패스는 특수한 ‘ RenderPass.SkyboxPass ’ 패스 모드를 사용하여 씬 환경의 스카이박스를 렌더링합니다. ‘ Qt Quick 3D ’는 ‘ SceneEnvironment ’의 ‘ lightProbe ’ 및 ‘ backgroundMode ’ 설정을 사용하여 스카이박스 지오메트리를 그리는 역할을 담당합니다.
PipelineStateOverride 는 깊이 테스트를 활성화하여 스카이박스가 씬 지오메트리 뒤에 올바르게 가려지도록 하지만, 스카이박스는 “무한원”에 위치하여 지오메트리를 가려서는 안 되므로 깊이 쓰기는 비활성화됩니다.
투명 오브젝트 서브패스
투명한 오브젝트는 뒤에서 앞으로 정렬된 블렌딩이 필요하기 때문에 G-버퍼에 저장될 수 없습니다. 대신 전용 서브패스를 통해 원래의 머티리얼을 사용하여 가장 마지막에 렌더링됩니다.
씬 내의 투명 원뿔은 다음과 같이 선언됩니다:
Model {
id: cone
layers: ContentLayer.Layer1
source: "#Cone"
y: 100
materials: [
PrincipledMaterial {
baseColor: Qt.rgba(0.0, 1.0, 0.0, 0.5)
alphaMode: PrincipledMaterial.Blend
metalness: 0.0
roughness: 0.5
}
]
}투명 서브패스는 매칭 레이어에서 투명한 렌더러블만 선택하기 위해 매칭 레이어 필터( RenderablesFilter )를 사용하며, 투명 레이어 필터( PipelineStateOverride )는 알파 블렌딩을 활성화하는 동시에 깊이 테스트를 유지하여 투명한 오브젝트가 불투명한 지오메트리에 대해 올바르게 정렬되도록 합니다.
투명한 오브젝트는 블렌딩이 발생하기 전에 깊이 버퍼가 완전히 채워지도록 모든 불투명 패스 이후에 렌더링되어야 합니다.
3D 서브패스 내의 2D 아이템
Qt Quick 3D 는 Node 를 컨테이너로 사용하여 표준 Qt Quick 2D 항목을 3D 씬 내에 삽입할 수 있습니다. 이러한 항목을 사용자 정의 렌더 파이프라인에 포함하려면 passMode 를 사용하여 서브패스를 추가하십시오: RenderPass.Item2DPass.
Node {
x: -200
y: 100
Item {
anchors.centerIn: parent
ColumnLayout {
Button {
text: "Click Me!"
}
Rectangle {
color: "blue"
implicitWidth: 50
implicitHeight: 50
NumberAnimation on rotation {
from: 0
to: 360
duration: 4000
loops: Animation.Infinite
running: true
}
}
}
}
NumberAnimation on eulerRotation.y {
from: 0
to: 360
duration: 6000
loops: Animation.Infinite
running: true
}
}Item2DPass 모드는 Qt Quick 3D 에 3D 노드의 자식인 모든 Qt Quick 항목을 현재 렌더 타깃에 렌더링하도록 지시하며, 이는 이미 존재하는 3D 콘텐츠와 합성됩니다.
화면에 렌더링하기
마지막으로, 사용자 정의 렌더 패스의 결과를 화면에 표시하려면 View3D 의 메인 컬러 텍스처가 메인 컬러 패스의 결과로 업데이트되도록 해야 합니다.
SimpleQuadRenderer {
texture: Texture {
textureProvider: mainColorPassProvider
}
}
RenderPassTexture {
id: mainColorTexture
format: RenderPassTexture.RGBA16F
}
RenderOutputProvider {
id: mainColorPassProvider
textureSource: RenderOutputProvider.UserPassTexture
renderPass: mainColorPass
attachmentSelector: RenderOutputProvider.Attachment0
}SimpleQuadRenderer 는 mainColorPass 에서 생성된 메인 컬러 텍스처를 View3D 의 프레임버퍼로 블릿하는 데 사용됩니다. RenderOutputProvider 는 mainColorPass 의 첫 번째 컬러 어태치먼트를 SimpleQuadRenderer 가 샘플링할 수 있는 텍스처로 노출합니다.
© 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.