环境(Environment):用于定义3D场景背景,可基于图片创建。它将环境贴图映射到立方体或球体表面(如等距柱状投影),以模拟真实环境背景;同时提供基于图像的光照(Image-Based Lighting,IBL),通过间接漫反射等方式影响物体环境光照,使物体更自然地融入场景,提升渲染真实感。
ArkGraphics 3D支持开发者创建环境资源,用于定义3D场景背景。
导入相关模块。
在页面脚本中导入ArkGraphics 3D提供的核心类型,用于创建场景、相机、材质、图片等对象。
import { Camera, Environment, Geometry, Image, Material, MaterialType, Scene, SceneResourceFactory,
SceneResourceParameters, Shader, ShaderMaterial, EnvironmentBackgroundType } from '@kit.ArkGraphics3D'; 加载场景并设置渲染参数。
调用Scene.load()方法加载.glb或.gltf格式的模型文件,并在加载完成后获取Scene对象。随后构建SceneOptions对象,指定场景及渲染模式,用于后续通过Component3D将场景内容渲染到界面中。
if (this.scene === null) {
// 从 .gltf 切换为 .glb;内容相同,格式不同
Scene.load($rawfile('gltf/CubeWithFloor/glTF/AnimatedCube.glb'))
.then(async (result: Scene) => {
// 将加载的场景赋值给globalScene,以便统一创建资源
globalScene = result;
this.scene = result;
this.sceneOpt = { scene: this.scene, modelType: ModelType.SURFACE } as SceneOptions;
this.rf = this.scene.getResourceFactory();
// ...
})
.catch((error: string) => {
console.error('init error: ' + error + '.');
});
} 初始化相机。
创建相机对象并设置相机启用状态与观察位置,用于后续展示模型。
this.cam = await this.rf.createCamera({ name: 'Camera1' });
this.cam.enabled = true;
this.cam.position.z = 5; 获取几何体节点。
通过Scene.getNodeByPath()方法获取目标模型的几何体(Geometry)节点,并记录其原始材质,以便在后续修改材质后可进行回退或恢复操作。
this.geom = this.scene.getNodeByPath('rootNode_/Unnamed Node 1/AnimatedCube') as Geometry;
// 记录原始材质
this.originalMat = this.geom.mesh.subMeshes[0].material; 创建环境并绑定图片。
使用SceneResourceFactory.createEnvironment()创建环境对象,并通过createImage()加载环境贴图。设置backgroundType为等距柱状投影背景,将图片绑定到environmentImage,再调整indirectDiffuseFactor等属性以控制环境光强度。
function createEnvironmentPromise() : Promise<Environment> {
return new Promise((resolve, reject) => {
// 确保在访问sceneFactory之前场景已加载
if (globalScene) {
let sceneFactory: SceneResourceFactory = globalScene.getResourceFactory();
// 手动加载环境贴图(.ktx/.jpg/.png等)
let sceneImageParameter: SceneResourceParameters = { name: 'image', uri: $rawfile('image/Cube_BaseColor.png') };
let image: Promise<Image> = sceneFactory.createImage(sceneImageParameter);
image.then(async (imageEntity: Image) => {
// 创建环境
let sceneEnvironmentParameter: SceneResourceParameters = { name: 'env' };
let env: Promise<Environment> = sceneFactory.createEnvironment(sceneEnvironmentParameter);
env.then(async (envEntity: Environment) => {
envEntity.backgroundType = EnvironmentBackgroundType.BACKGROUND_EQUIRECTANGULAR;
envEntity.environmentImage = imageEntity;
// 设置环境相关属性
envEntity.indirectDiffuseFactor.x = 1;
envEntity.indirectDiffuseFactor.y = 1;
envEntity.indirectDiffuseFactor.z = 1;
envEntity.indirectDiffuseFactor.w = 1;
resolve(envEntity);
}).catch((err: string) => {
console.error('Environment mapping material create failed: ' + err + '.');
reject(err);
});
}).catch((err: string) => {
console.error('Image load failed: ' + err);
reject(err);
});
} else {
reject('Scene is not loaded yet.');
}
});
} 应用环境到场景。
在按钮点击事件中调用createEnvironmentPromise()创建环境资源,并将其赋值给场景的environment属性,使环境背景立即生效。
Button('Add to Environment')
// ...
.onClick(async (): Promise<void> => {
console.info('Start to replace with a material of image');
if (!this.scene || !this.cam) {
return;
}
this.env = await createEnvironmentPromise();
if (this.env) {
this.scene.environment = this.env;
}
});