Qt Quick 3D - 프로시저럴 텍스처 예제
C++ 또는 QML에서 커스텀 텍스처 데이터를 제공하는 방법을 보여줍니다.
이 예제에서는 QQuick3DTextureData 및 the textureData property 의 텍스처를 사용하여 정적 에셋에서 로드하는 대신 런타임에 동적으로 생성된 텍스처 데이터를 제공합니다. 데모를 위해 이 예제에서는 각각 C++와 QML로 두 개의 그라데이션 텍스처를 생성합니다.
먼저 텍스처 데이터에 대한 C++ 클래스를 정의합니다. QQuick3DTextureData 의 서브클래스로 만듭니다. 가상 함수가 없기 때문에 꼭 필요한 것은 아니지만 모든 것을 하나의 클래스에 넣는 것이 훨씬 더 편리합니다. 사용할 프로퍼티를 정의하고 QML_NAMED_ELEMENT 을 추가하여 QML에서 사용할 수 있도록 합니다:
class GradientTexture : public QQuick3DTextureData { Q_OBJECT Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) Q_PROPERTY(QColor startColor READ startColor WRITE setStartColor NOTIFY startColorChanged) Q_PROPERTY(QColor endColor READ endColor WRITE setEndColor NOTIFY endColorChanged) QML_NAMED_ELEMENT(GradientTexture) ...
텍스처를 업데이트하는 함수를 추가합니다. 텍스처를 구성하는 데는 setSize와 setFormat을 사용하고 이미지 데이터를 설정하는 데는 setTextureData를 사용합니다:
void GradientTexture::updateTexture() { setSize(QSize(m_width, m_height)); setFormat(QQuick3DTextureData::RGBA8); setHasTransparency(false); setTextureData(generateTexture()); }
generateTexture
함수는 올바른 크기의 QByteArray 을 생성하고 이미지 데이터로 채웁니다:
QByteArray GradientTexture::generateTexture() { QByteArray imageData; // Create a horizontal gradient between startColor and endColor // Create a single scanline and reuse that data for each QByteArray gradientScanline; gradientScanline.resize(m_width * 4); // RGBA8 for (int x = 0; x < m_width; ++x) { QColor color = linearInterpolate(m_startColor, m_endColor, x / float(m_width)); int offset = x * 4; gradientScanline.data()[offset + 0] = char(color.red()); gradientScanline.data()[offset + 1] = char(color.green()); gradientScanline.data()[offset + 2] = char(color.blue()); gradientScanline.data()[offset + 3] = char(255); } for (int y = 0; y < m_height; ++y) imageData += gradientScanline; return imageData; }
프로퍼티가 변경될 때마다 updateTexture
함수를 호출합니다:
void GradientTexture::setStartColor(QColor startColor) { if (m_startColor == startColor) return; m_startColor = startColor; emit startColorChanged(m_startColor); updateTexture(); }
마지막으로 QML에서 새 텍스처를 사용할 수 있습니다:
Texture { id: textureFromCpp minFilter: applicationState.filterMode magFilter: applicationState.filterMode textureData: gradientTexture GradientTexture { id: gradientTexture startColor: applicationState.startColor endColor: applicationState.endColor width: applicationState.size height: width } }
QML에서도 동일한 텍스처 데이터를 생성할 수 있습니다. 이 경우 ProceduralTextureData 컴포넌트를 사용합니다:
Texture { id: textureFromQML minFilter: applicationState.filterMode magFilter: applicationState.filterMode textureData: gradientTextureDataQML ProceduralTextureData { id: gradientTextureDataQML property color startColor: applicationState.startColor property color endColor: applicationState.endColor width: applicationState.size height: width textureData: generateTextureData() function linearInterpolate(startColor : color, endColor : color, fraction : real) : color{ return Qt.rgba( startColor.r + (endColor.r - startColor.r) * fraction, startColor.g + (endColor.g - startColor.g) * fraction, startColor.b + (endColor.b - startColor.b) * fraction, startColor.a + (endColor.a - startColor.a) * fraction ); } function generateTextureData() { let dataBuffer = new ArrayBuffer(width * height * 4) let data = new Uint8Array(dataBuffer) let gradientScanline = new Uint8Array(width * 4); for (let x = 0; x < width; ++x) { let color = linearInterpolate(startColor, endColor, x / width); let offset = x * 4; gradientScanline[offset + 0] = color.r * 255; gradientScanline[offset + 1] = color.g * 255; gradientScanline[offset + 2] = color.b * 255; gradientScanline[offset + 3] = color.a * 255; } for (let y = 0; y < height; ++y) { data.set(gradientScanline, y * width * 4); } return dataBuffer; } } }
C++에서와 마찬가지로 텍스처의 크기와 형식을 반영하는 이미지 데이터로 QByteArray 를 채웁니다. QML에서 이 작업을 수행할 때는 불필요한 유형 변환을 피하기 위해 ArrayBuffer 유형을 사용합니다.
© 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.