Qt Quick 3D - 커스텀 인스턴스 렌더링

커스텀 머티리얼과 C++ 인스턴스 테이블을 사용한 인스턴싱을 시연합니다.

이 예제에서는 C++에서 프로그래밍 방식으로 인스턴스 데이터를 생성하는 방법과 인스턴스 렌더링에 커스텀 머티리얼을 사용하는 방법을 보여줍니다.

커스텀 인스턴싱 테이블

테이블을 QQuick3DInstancing 의 서브클래스로 정의하고 몇 가지 프로퍼티를 추가하여 QML에서 제어할 수 있도록 합니다:

class CppInstanceTable : public QQuick3DInstancing
{
    Q_OBJECT
    QML_ELEMENT

    Q_PROPERTY(int gridSize READ gridSize WRITE setGridSize NOTIFY gridSizeChanged)
    Q_PROPERTY(float gridSpacing READ gridSpacing WRITE setGridSpacing NOTIFY gridSpacingChanged)
    Q_PROPERTY(int randomSeed READ randomSeed WRITE setRandomSeed NOTIFY randomSeedChanged)

가상 함수 getInstanceBuffer 를 다시 구현하여 인스턴싱 데이터를 반환합니다:

QByteArray CppInstanceTable::getInstanceBuffer(int *instanceCount)
{
    if (m_dirty) {
        BlockTable blocks(m_gridSize, m_randomSeed);
        m_instanceData.resize(0);

        auto idxToPos = [this](int i) -> float { return m_gridSpacing * (i - m_gridSize / 2); };

        int instanceNumber = 0;
        for (int i = 0; i < m_gridSize; ++i) {
            float xPos = idxToPos(i);
            for (int j = 0; j < m_gridSize; ++j) {
                float zPos = idxToPos(j);
                int lowest = blocks.lowestVisible(i, j);
                int highest = blocks.highestBlock(i, j);
                for (int k = lowest; k <= highest; ++k) {
                    float yPos = idxToPos(k);
                    QColor color = blocks.getBlockColor(i, j, k);
                    float waterAnimation = blocks.isWaterSurface(i, j, k) ? 1.0 : 0.0;
                    auto entry = calculateTableEntry({ xPos, yPos, zPos }, { 1.0, 1.0, 1.0 }, {}, color, { waterAnimation, 0, 0, 0 });
                    m_instanceData.append(reinterpret_cast<const char *>(&entry), sizeof(entry));
                    instanceNumber++;
                }
            }
        }
        m_instanceCount = instanceNumber;
        m_dirty = false;
    }
    if (instanceCount)
        *instanceCount = m_instanceCount;

    return m_instanceData;
}

커스텀 머티리얼

음영 처리된 커스텀 머티리얼을 사용하므로 Qt에서 기본 구현을 제공하고 추가 로직만 지정하면 됩니다.

버텍스 셰이더에 필요한 유일한 커스터마이징은 조각 셰이더에 정보를 전달하기 위한 것입니다. 기본적으로 Qt는 버텍스 셰이더에 인스턴스 데이터만 제공하므로 vCustomData 로 전달합니다. 또한 버텍스의 전역 위치도 계산하여 vGlobalPosition 로 제공합니다.

// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

VARYING vec4 vCustomData;
VARYING vec3 vGlobalPosition;
void MAIN()
{
    vCustomData = INSTANCE_DATA;

    // MODEL_MATRIX does not exist when instancing
    vec4 pos = INSTANCE_MODEL_MATRIX * vec4(VERTEX, 1.0);
    vGlobalPosition = pos.xyz;
}

프래그먼트 셰이더는 물 표면에 대한 간단한 물결 애니메이션을 수행합니다. 다른 모든 것에는 미묘한 방사형 그라데이션이 적용됩니다. 차이점은 사용자 지정 데이터의 첫 번째 요소에 의해 결정됩니다.

VARYING vec4 vCustomData;
VARYING vec3 vGlobalPosition;

void MAIN()
{
    METALNESS = 0.0;
    ROUGHNESS = 1.0;
    FRESNEL_POWER = 5.0;

    float c;

    if (vCustomData.x > 0)
        c = 1.0 - (1.0 + sin(sqrt(vGlobalPosition.x*vGlobalPosition.x + vGlobalPosition.z*vGlobalPosition.z) - uTime/200.0)) * 0.2;
    else
        c = 1.0 - 0.25 * (UV0.x*UV0.x + UV0.y*UV0.y);

    BASE_COLOR = vec4(c, c, c, 1.0);
}

QML에서 커스텀 테이블 및 머티리얼 사용

앞서 만든 셰이더를 사용하여 커스텀 머티리얼을 만들고 새 속성 uTime 을 추가합니다. 이 프로퍼티는 조각 셰이더의 해당 유니폼에 자동으로 매핑됩니다.

CustomMaterial {
    id: cubeMaterial
    property real uTime: frametimer.elapsedTime
    FrameAnimation {
        id: frametimer
        running: true
    }

    vertexShader: "cubeMaterial.vert"
    fragmentShader: "cubeMaterial.frag"
}

마지막으로 모델을 생성하고 커스텀 머티리얼과 인스턴스 테이블을 적용합니다:

Model {
    id: instancedCube
    property real cubeSize: 15
    scale: Qt.vector3d(cubeSize/100, cubeSize/100, cubeSize/100)
    source: "#Cube"
    instancing: CppInstanceTable {
        gridSize: 65
        gridSpacing: instancedCube.cubeSize
        randomSeed: 1522562186
    }
    materials: [ cubeMaterial ]
}

단 하나의 큐브만 생성한다는 점에 유의하세요: 모든 무거운 작업은 GPU에서 수행합니다.

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

© 2025 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.