在 Godot 中,Material(材质)是一个重要的概念,用于定义 3D 对象的表面属性和视觉效果。
什么是 Material
Material 控制着 3D 对象的外观,包括颜色、纹理、光照反应、透明度等视觉属性。它决定了物体在不同光照条件下的渲染效果。
主要类型
Godot 提供了几种不同的 Material 类型:
StandardMaterial3D:最常用的材质类型,支持基于物理的渲染(PBR)。它包含了现代 3D 图形的标准属性,如反射率、金属度、粗糙度等。
ShaderMaterial:使用自定义着色器的材质,提供最大的灵活性。你可以编写自己的着色器代码来实现特殊效果。
ORMMaterial3D:专门用于 ORM(Occlusion, Roughness, Metallic)贴图的材质。
常用属性
StandardMaterial3D 的主要属性包括:
- Albedo:基础颜色和纹理
- Metallic:金属度,控制材质的金属感
- Roughness:粗糙度,影响反射的锐利程度
- Emission:自发光属性
- Normal:法线贴图,用于模拟表面细节
- Transparency:透明度设置
使用方法
你可以通过以下方式应用 Material:
- 在编辑器中为 MeshInstance3D 节点分配材质
- 通过代码动态设置材质属性
- 创建材质资源文件(.tres)供多个对象共享
Material 系统让你能够创建从简单的纯色表面到复杂的写实材质的各种视觉效果,是 Godot 3D 渲染管线的核心组件。
示例(CPP)
以下是使用 GDExtension(C++)创建和操作各种材质类型的完整示例,包括基础色、金属、发光、透明、玻璃、纹理、水面、自定义着色器材质的创建,以及材质属性动画、状态切换、批量应用和资源文件的保存加载。
// material_examples.h
#ifndef MATERIAL_EXAMPLES_H
#define MATERIAL_EXAMPLES_H
#include <godot_cpp/classes/node3d.hpp>
#include <godot_cpp/classes/mesh_instance3d.hpp>
#include <godot_cpp/classes/standard_material3d.hpp>
#include <godot_cpp/classes/shader_material.hpp>
#include <godot_cpp/classes/shader.hpp>
#include <godot_cpp/classes/texture2d.hpp>
#include <godot_cpp/classes/resource_loader.hpp>
#include <godot_cpp/classes/resource_saver.hpp>
#include <godot_cpp/classes/tween.hpp>
using namespace godot;
class MaterialExamples : public Node3D {
GDCLASS(MaterialExamples, Node3D)
private:
MeshInstance3D* mesh_instance;
protected:
static void _bind_methods();
public:
MaterialExamples();
~MaterialExamples();
void _ready() override;
// 基础材质创建
Ref<StandardMaterial3D> create_basic_material();
Ref<StandardMaterial3D> create_metal_material();
Ref<StandardMaterial3D> create_emissive_material();
Ref<StandardMaterial3D> create_transparent_material();
Ref<StandardMaterial3D> create_glass_material();
Ref<StandardMaterial3D> create_textured_material();
Ref<StandardMaterial3D> create_water_material();
// 着色器材质
Ref<ShaderMaterial> create_shader_material();
// 动态材质操作
void animate_material_properties();
void switch_material_based_on_state(bool is_active);
void apply_material_to_multiple_objects();
// 资源管理
void save_material_as_resource();
void load_material_from_resource();
// 材质属性动态修改
void update_material_properties(float delta_time);
};
#endif // MATERIAL_EXAMPLES_H
// material_examples.cpp
#include "material_examples.h"
#include <godot_cpp/core/class_db.hpp>
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
void MaterialExamples::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_basic_material"), &MaterialExamples::create_basic_material);
ClassDB::bind_method(D_METHOD("create_metal_material"), &MaterialExamples::create_metal_material);
ClassDB::bind_method(D_METHOD("create_emissive_material"), &MaterialExamples::create_emissive_material);
ClassDB::bind_method(D_METHOD("create_transparent_material"), &MaterialExamples::create_transparent_material);
ClassDB::bind_method(D_METHOD("create_glass_material"), &MaterialExamples::create_glass_material);
ClassDB::bind_method(D_METHOD("create_textured_material"), &MaterialExamples::create_textured_material);
ClassDB::bind_method(D_METHOD("create_water_material"), &MaterialExamples::create_water_material);
ClassDB::bind_method(D_METHOD("create_shader_material"), &MaterialExamples::create_shader_material);
ClassDB::bind_method(D_METHOD("animate_material_properties"), &MaterialExamples::animate_material_properties);
ClassDB::bind_method(D_METHOD("switch_material_based_on_state"), &MaterialExamples::switch_material_based_on_state);
ClassDB::bind_method(D_METHOD("apply_material_to_multiple_objects"), &MaterialExamples::apply_material_to_multiple_objects);
ClassDB::bind_method(D_METHOD("save_material_as_resource"), &MaterialExamples::save_material_as_resource);
ClassDB::bind_method(D_METHOD("load_material_from_resource"), &MaterialExamples::load_material_from_resource);
}
MaterialExamples::MaterialExamples() {
mesh_instance = nullptr;
}
MaterialExamples::~MaterialExamples() {
// 析构函数
}
void MaterialExamples::_ready() {
// 获取MeshInstance3D子节点
mesh_instance = get_node<MeshInstance3D>("MeshInstance3D");
if (!mesh_instance) {
UtilityFunctions::print("MeshInstance3D not found!");
return;
}
// 创建并应用基础材质
Ref<StandardMaterial3D> material = create_basic_material();
mesh_instance->set_material_override(material);
}
// 示例1:创建基础材质
Ref<StandardMaterial3D> MaterialExamples::create_basic_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 设置基础颜色
material->set_albedo(Color(1.0, 0.0, 0.0, 1.0)); // 红色
return material;
}
// 示例2:创建金属材质
Ref<StandardMaterial3D> MaterialExamples::create_metal_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 设置金属属性
material->set_albedo(Color(0.7, 0.7, 0.8, 1.0)); // 银色
material->set_metallic(1.0); // 完全金属
material->set_roughness(0.2); // 低粗糙度
material->set_specular(1.0); // 高镜面反射
return material;
}
// 示例3:创建发光材质
Ref<StandardMaterial3D> MaterialExamples::create_emissive_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 设置发光属性
material->set_albedo(Color(0.0, 0.0, 1.0, 1.0)); // 蓝色基础
material->set_flag(BaseMaterial3D::FLAG_EMISSION, true); // 启用发光
material->set_emission(Color(0.0, 0.0, 1.0)); // 蓝色发光
material->set_emission_energy(2.0); // 发光强度
return material;
}
// 示例4:创建透明材质
Ref<StandardMaterial3D> MaterialExamples::create_transparent_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 设置透明度
material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
material->set_albedo(Color(1.0, 1.0, 1.0, 0.5)); // 半透明白色
return material;
}
// 示例5:创建玻璃材质
Ref<StandardMaterial3D> MaterialExamples::create_glass_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 玻璃属性
material->set_albedo(Color(0.9, 0.9, 1.0, 0.1)); // 几乎透明
material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
material->set_metallic(0.0);
material->set_roughness(0.0); // 完全光滑
// 启用折射
material->set_flag(BaseMaterial3D::FLAG_REFRACTION, true);
material->set_refraction(0.05);
return material;
}
// 示例6:创建带纹理的材质
Ref<StandardMaterial3D> MaterialExamples::create_textured_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 加载纹理
Ref<Texture2D> texture = ResourceLoader::get_singleton()->load("res://textures/my_texture.png");
if (texture.is_valid()) {
material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, texture);
material->set_uv1_scale(Vector3(2.0, 2.0, 1.0)); // 纹理缩放
}
return material;
}
// 示例7:创建水面材质
Ref<StandardMaterial3D> MaterialExamples::create_water_material() {
Ref<StandardMaterial3D> material;
material.instantiate();
// 基础属性
material->set_albedo(Color(0.1, 0.3, 0.8, 0.8));
material->set_transparency(BaseMaterial3D::TRANSPARENCY_ALPHA);
// 反射和粗糙度
material->set_metallic(0.0);
material->set_roughness(0.1);
// 法线贴图
Ref<Texture2D> normal_texture = ResourceLoader::get_singleton()->load("res://textures/water_normal.png");
if (normal_texture.is_valid()) {
material->set_flag(BaseMaterial3D::FLAG_NORMAL_MAP, true);
material->set_texture(BaseMaterial3D::TEXTURE_NORMAL, normal_texture);
material->set_uv1_scale(Vector3(4.0, 4.0, 1.0));
}
return material;
}
// 示例8:创建着色器材质
Ref<ShaderMaterial> MaterialExamples::create_shader_material() {
Ref<ShaderMaterial> material;
material.instantiate();
// 加载自定义着色器
Ref<Shader> shader = ResourceLoader::get_singleton()->load("res://shaders/my_shader.gdshader");
if (shader.is_valid()) {
material->set_shader(shader);
// 设置着色器参数
material->set_shader_parameter("time_scale", 1.0);
material->set_shader_parameter("color_tint", Color(0.0, 1.0, 0.0, 1.0));
}
return material;
}
// 示例9:动画化材质属性
void MaterialExamples::animate_material_properties() {
if (!mesh_instance) return;
Ref<StandardMaterial3D> material = mesh_instance->get_material_override();
if (material.is_null()) {
material = create_emissive_material();
mesh_instance->set_material_override(material);
}
// 创建Tween动画
Ref<Tween> tween = create_tween();
tween->set_loops();
// 动画化发光强度
Callable emission_callback = callable_mp(this, &MaterialExamples::_on_emission_tween_step);
tween->tween_method(emission_callback, 0.0, 3.0, 2.0);
tween->tween_method(emission_callback, 3.0, 0.0, 2.0);
}
// Tween回调函数
void MaterialExamples::_on_emission_tween_step(float value) {
if (!mesh_instance) return;
Ref<StandardMaterial3D> material = mesh_instance->get_material_override();
if (material.is_valid()) {
material->set_emission_energy(value);
}
}
// 示例10:根据状态切换材质
void MaterialExamples::switch_material_based_on_state(bool is_active) {
if (!mesh_instance) return;
Ref<StandardMaterial3D> material;
if (is_active) {
material = create_emissive_material();
} else {
material = create_basic_material();
material->set_albedo(Color(0.5, 0.5, 0.5, 1.0)); // 灰色
}
mesh_instance->set_material_override(material);
}
// 示例11:批量应用材质
void MaterialExamples::apply_material_to_multiple_objects() {
Ref<StandardMaterial3D> shared_material = create_metal_material();
// 获取所有MeshInstance3D子节点
TypedArray<Node> children = get_children();
for (int i = 0; i < children.size(); i++) {
MeshInstance3D* mesh_node = Object::cast_to<MeshInstance3D>(children[i]);
if (mesh_node) {
mesh_node->set_material_override(shared_material);
}
}
}
// 示例12:保存材质资源
void MaterialExamples::save_material_as_resource() {
Ref<StandardMaterial3D> material = create_metal_material();
// 保存材质为资源文件
ResourceSaver::get_singleton()->save(material, "res://materials/metal_material.tres");
}
// 示例13:加载材质资源
void MaterialExamples::load_material_from_resource() {
if (!mesh_instance) return;
// 从资源文件加载材质
Ref<StandardMaterial3D> material = ResourceLoader::get_singleton()->load("res://materials/metal_material.tres");
if (material.is_valid()) {
mesh_instance->set_material_override(material);
}
}
// 示例14:实时更新材质属性
void MaterialExamples::update_material_properties(float delta_time) {
if (!mesh_instance) return;
Ref<StandardMaterial3D> material = mesh_instance->get_material_override();
if (material.is_null()) return;
// 获取当前时间
static float time = 0.0f;
time += delta_time;
// 动态修改发光强度
if (material->get_flag(BaseMaterial3D::FLAG_EMISSION)) {
float emission_intensity = (sin(time * 2.0f) + 1.0f) * 0.5f * 3.0f;
material->set_emission_energy(emission_intensity);
}
// 动态修改粗糙度
float roughness = (sin(time) + 1.0f) * 0.5f;
material->set_roughness(roughness);
}
// 私有帮助函数
void MaterialExamples::_on_emission_tween_step(float value) {
if (!mesh_instance) return;
Ref<StandardMaterial3D> material = mesh_instance->get_material_override();
if (material.is_valid()) {
material->set_emission_energy(value);
}
}