Qt Quick 3D - 사용자 정의 재료 예시
셰이딩이 적용된 사용자 정의 머티리얼을 작성하는 방법을 보여줍니다.

이 예제는 셰이딩이 적용된 사용자 정의 매터리얼( custom materials)을 작성하는 방법을 보여줍니다. 셰이딩이 적용된 매터리얼을 사용하면 완전한 셰이더 프로그램을 작성할 필요가 없습니다. 대신, Qt의 표준 셰이더를 수정하는 함수를 작성하면 됩니다. 이렇게 하면 생성된 매터리얼은 기본적으로 조명 및 섀도 매핑에 참여하며, 라이트 프로브와 호환됩니다. 특수한 동작이 필요한 경우에만 사용자 정의 로직을 작성하면 됩니다. 이는 PrincipledMaterial 에 대해 생성될 셰이더 코드를, 버텍스 및 프래그먼트 셰이더의 특정 단계에서 호출되는 자체 사용자 정의 함수로 효과적으로 보완함으로써 달성됩니다.
셰이딩이 적용된 사용자 정의 머티리얼을 만들려면, ` shadingMode ` 속성을 ` CustomMaterial.Shaded`로 설정하십시오.
간단한 머티리얼
첫 번째 모델은 사용자 정의 로직을 추가하지 않는 간단한 머티리얼을 사용합니다. 다른 머티리얼과 마찬가지로 모델에 사용자 정의 머티리얼을 설정합니다:
Model {
source: "weirdShape.mesh"
scale: Qt.vector3d(100, 100, 100)
rotation: Quaternion.fromEulerAngles(-90, 0, 0)
x: v3d.radius
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_simple.frag"
property color uDiffuse: "fuchsia"
property real uSpecular: 1.0
}
]
}shadingMode 와 fragmentShader 을 설정하는 것 외에도, 머티리얼에 uDiffuse 와 Specular 라는 두 가지 속성을 추가합니다. 이 속성들은 프래그먼트 셰이더에서 인식됩니다.
프래그먼트 셰이더의 코드는 짧습니다:
void MAIN()
{
SPECULAR_AMOUNT = uSpecular;
BASE_COLOR = uDiffuse;
}모든 셰이더는 MAIN 함수를 구현해야 합니다. 이 함수에서는 머티리얼에 정의된 속성을 사용하여 Qt의 표준 셰이더 코드에서 사용할 값을 설정합니다. 이 값들을 유니폼(uniform)으로 선언할 필요는 없으며, 이름만 일치하도록 하면 됩니다. 머티리얼에 일치하는 속성이 없다면 셰이더 컴파일 오류가 발생합니다.
특수 변수 ` SPECULAR_AMOUNT `와 ` BASE_COLOR `는 PrincipledMaterial 의 ` specularAmount ` 및 ` baseColor `에 해당합니다. 이 변수들은 표준 셰이더 코드에서 마치 ` PrincipledMaterial`를 사용한 것처럼 조명 계산을 수행하는 데 사용됩니다.
조명의 사용자 정의 처리
다음 오브젝트는 사용자 정의 조명을 구현하는 더 복잡한 머티리얼을 사용합니다. 이 머티리얼은 유니폼 이름이 다르지만, 그 외에는 동일한 방식으로 사용됩니다:
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_customlights.frag"
property color uDiffuse: "orange"
property real uShininess: 150
}
]프래그먼트 셰이더는 다양한 유형의 조명에 대한 사용자 정의 로직을 구현합니다:
void MAIN()
{
SPECULAR_AMOUNT = 1.0;
ROUGHNESS = 0.5;
BASE_COLOR = uDiffuse;
}
void AMBIENT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * TOTAL_AMBIENT_COLOR;
}
void DIRECTIONAL_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(NORMAL), TO_LIGHT_DIR)));
}
void POINT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * LIGHT_ATTENUATION * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(NORMAL), TO_LIGHT_DIR)));
}
void SPOT_LIGHT()
{
DIFFUSE += uDiffuse.rgb * LIGHT_COLOR * LIGHT_ATTENUATION * SPOT_FACTOR * SHADOW_CONTRIB * vec3(max(0.0, dot(normalize(VAR_WORLD_NORMAL), TO_LIGHT_DIR)));
}여기서는 다양한 조명 유형의 속성을 참조하는 여러 가지 새로운 특수 키워드를 사용합니다. 각 키워드에 대한 설명은 CustomMaterial 문서를 참조하십시오. 각 조명 유형마다 고유한 함수가 있다는 점에 유의하십시오. 구현되지 않은 함수는 기본 구현을 사용하며, PrincipledMaterial 와 같은 동작을 보입니다. 예를 들어, 이 셰이더에서는 SPECULAR_LIGHT() 를 구현하지 않았으므로 내장된 스페큘러 반사 효과가 적용됩니다.
버텍스 셰이더 추가하기
사용자 정의 머티리얼은 버텍스 셰이더를 사용하여 모델의 지오메트리를 수정할 수도 있습니다. 여기서는 프래그먼트 셰이더와 버텍스 셰이더를 모두 지정하고, 유니폼 값으로 사용될 몇 가지 속성을 더 추가합니다:
materials: [
CustomMaterial {
id: material
shadingMode: CustomMaterial.Shaded
vertexShader: "material_distortion.vert"
fragmentShader: "material_customlights.frag"
property real uTime: 0.0
property real uAmplitude: 0.3
property color uDiffuse: "yellow"
property real uShininess: 50
NumberAnimation {
target: material
property: "uTime"
from: 0.0
to: 31.4
duration: 10000
loops: Animation.Infinite
running: true
}
}
]버텍스 셰이더는 매우 짧습니다:
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void MAIN()
{
VERTEX.y += sin(uTime + VERTEX.x*10.0) * uAmplitude;
}이는 시간에 따라 변화하는 사인파에 따라 각 정점을 변위시켜 모델의 형태를 변형시킵니다.
투명한 머티리얼
마지막으로, 투명한 머티리얼을 적용한 구체를 추가합니다. 성능상의 이유로 Qt는 투명도를 완전히 사실적인 방식으로 구현하지 않습니다. 대신, Qt는 씬 내의 모든 불투명한 오브젝트를 텍스처로 렌더링한 다음, 투명한 머티리얼이 이 텍스처에서 값을 읽어옵니다. 즉, 투명한 머티리얼은 다른 오브젝트 앞에 배치되었을 때 최상의 결과를 보여줍니다:
Model {
id: screenSphere
source: "#Sphere"
scale: Qt.vector3d(0.75, 0.75, 0.75)
y: 60
z: 750;
materials: [
CustomMaterial {
shadingMode: CustomMaterial.Shaded
fragmentShader: "material_transparent.frag"
}
]이 예제에서는 실제 물리학적 굴절을 시도하지 않는 단순한 왜곡 함수를 구현합니다:
void MAIN()
{
vec2 size = vec2(textureSize(SCREEN_TEXTURE, 0));
vec2 uv = FRAGCOORD.xy / size;
vec3 view = normalize(VIEW_VECTOR);
vec3 projection = view - view * normalize(NORMAL);
vec3 refraction = projection * projection;
uv += refraction.xy * 0.5;
vec3 col = texture(SCREEN_TEXTURE, uv).rgb;
col = col * 0.8 + vec3(0.2);
BASE_COLOR = vec4(col, 1.0);
}SCREEN_TEXTURE 는 장면 내의 모든 불투명 오브젝트를 보여주는 텍스처를 가리킵니다. 먼저 현재 정점의 화면 위치와 일치하는 이 텍스처 내의 UV 좌표를 계산합니다. 그런 다음 텍스처 조회 작업을 수행하기 전에 이 위치에 오프셋을 더해 굴절 효과를 시뮬레이션합니다.
마지막으로, 약간의 흐릿함을 주기 위해 20%의 흰색을 블렌딩합니다. 출력이 ` BASE_COLOR`에 할당되므로 Qt가 여기에 조명을 추가한다는 점에 유의하십시오. 이것이 바로 구의 표면에 반사가 보이는 이유입니다.
쉐이딩되지 않은 머티리얼
편의 키워드를 계속 사용하면서도 완전한 셰이더 프로그램을 활용하는 사용자 정의 머티리얼을 구현할 수도 있습니다. customshaders 예제는 사용자 정의 머티리얼의 또 다른 유형인 ‘언셰이딩 사용자 정의 머티리얼’을 보여줍니다.
© 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.