• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import scene3d from '@ohos.graphics.scene'
17import animator, { AnimatorResult } from '@ohos.animator';
18import router from '@ohos.router';
19import Logger from '../util/Logger';
20
21@Entry
22@Component
23struct sceneShader {
24  scene: scene3d.Scene | null = null;
25  @State sceneOpt: SceneOptions | null = null;
26  rf: scene3d.SceneResourceFactory | null = null;
27  cam: scene3d.Camera | null = null;
28  shader: scene3d.Shader | null = null;
29  material: scene3d.ShaderMaterial | null = null;
30  geom: scene3d.Geometry | null = null;
31  image: scene3d.Image | null = null;
32  materialOrg: scene3d.Material | null = null;
33  backAnimator: AnimatorResult | undefined = undefined;
34  step: number = 0;
35  @State hierarchy: string = '';
36  @State meshInfo: string = '';
37
38  traversal(node: scene3d.Node | null): void {
39    if (!node) {
40      return;
41    }
42    this.hierarchy += node.path + '/' + node.name + '\n';
43    let container: scene3d.Container<scene3d.Node> = node.children;
44    let count: number = container.count();
45    this.hierarchy += '  ';
46    for (let i = 0; i < count; i++) {
47      this.traversal(container.get(i));
48    }
49  }
50
51  onPageShow(): void {
52    this.init();
53  }
54
55  PrintAabb(aabb: scene3d.Aabb, append: string): string {
56    let info: string = ''
57    info += append + " max aabb [ " + aabb.aabbMax.x + " "+ aabb.aabbMax.y + " "+ aabb.aabbMax.z + " ]";
58    info += "\n" + append + " min aabb [ " + aabb.aabbMin.x + " "+ aabb.aabbMin.y + " "+ aabb.aabbMin.z + " ]";
59    return info;
60  }
61
62  onPageHide(): void {
63    if (this.scene) {
64      this.scene.destroy();
65    }
66
67    this.cam = null;
68    this.scene = null;
69  }
70
71  init(): void {
72    this.backAnimator = animator.create({
73      duration: 2000, // duration
74      easing: "ease",
75      delay: 0,
76      fill: "none",
77      direction: "normal",
78      iterations: -1, // endless loop
79      begin: 100, // begin
80      end: 200 // end
81    })
82    this.backAnimator.onframe = value => {
83      this.step++;
84      if (this.material && this.material.colorShader) {
85        // just give a random effect
86        (this.material.colorShader.inputs["vec_1"] as scene3d.Vec4) = { x: Math.abs(Math.sin(this.step) + 0.5),
87          y: Math.abs(Math.sin(this.step * 0.86) + 0.5),
88               z: Math.abs(Math.sin(this.step * 0.91) + 0.5), w: 1.0 };
89        (this.material.colorShader.inputs["time"] as number) = this.step;
90      }
91    }
92    if (this.scene === null) {
93      scene3d.Scene.load($rawfile("gltf/Cube/glTF/Cube.glb"))
94        .then(async (result: scene3d.Scene) => {
95          this.scene = result;
96          this.sceneOpt = { scene: this.scene, modelType: ModelType.SURFACE } as SceneOptions;
97          this.rf = this.scene.getResourceFactory();
98          this.cam = await this.rf.createCamera({ "name": "Camera1" });
99          this.cam.enabled = true;
100          this.cam.position.z = 5; // put camera to 5 at z
101
102          this.image = await this.rf.createImage({ name: "envImg3", uri: $rawfile("gltf/DamagedHelmet/glTF/Default_AO.jpg") });
103          this.traversal(this.scene?.root);
104          if (!this.geom) {
105            this.geom = this.scene.getNodeByPath("rootNode_/Unnamed Node 1/Cube") as scene3d.Geometry;
106            this.meshInfo += this.PrintAabb(this.geom.mesh.aabb, 'Mesh ');
107            let i = 0;
108            for (let M of this.geom.mesh.subMeshes) {
109              this.meshInfo += '\n';
110              this.meshInfo += this.PrintAabb(this.geom.mesh.aabb, 'Submesh[' + i + "]");
111              i++;
112            }
113
114          }
115          this.materialOrg = this.geom.mesh.subMeshes[0].material;
116
117        })
118        .catch((reason: string) => {
119          Logger.error("init error", reason);
120        });
121    }
122  }
123
124  build() {
125    Row() {
126      Column() {
127        Column() {
128          if (this.sceneOpt) {
129            Component3D(this.sceneOpt)
130              .renderWidth('60%')
131              .renderHeight('60%').onAppear(()=>{
132               this.backAnimator?.play()
133            })
134          }
135          else {
136            Text("loading 1...");
137          }
138        }
139        .height('30%')
140
141        Button('create shader and change material').onClick(async () => {
142          if (!this.scene || !this.rf) {
143            return;
144          }
145          if (!this.material) {
146            this.material = await this.rf.createMaterial({ name: "CustomMaterial" }, scene3d.MaterialType.SHADER);
147          }
148          if (!this.shader) {
149            this.shader = await this.rf.createShader({ name: "CustomShader", uri: $rawfile("shaders/custom_shader/custom_material_sample.shader") });
150          }
151
152          if (this.material) {
153            this.material.colorShader = this.shader;
154          }
155
156          if (!this.geom) {
157            this.geom = this.scene.getNodeByPath("rootNode_/Unnamed Node 1/Cube") as scene3d.Geometry;
158          }
159
160           this.geom.mesh.materialOverride = undefined;
161           this.geom.mesh.subMeshes[0].material = this.material;
162
163          if (this.material && this.material.colorShader && this.image) {
164            (this.material.colorShader.inputs["BASE_COLOR_Image"] as scene3d.Image) = this.image;
165          }
166        }).id('create_shader_change_material');
167
168        Button('recovery original material').onClick(async () => {
169          if (this.geom) {
170            this.geom.mesh.materialOverride = undefined;
171            this.geom.mesh.subMeshes[0].material = this.materialOrg as scene3d.ShaderMaterial;
172          }
173        }).id('recovery_original')
174
175        Button('material override').onClick(async () => {
176          if (this.geom) {
177            this.geom.mesh.subMeshes[0].material = this.materialOrg as scene3d.ShaderMaterial;
178          }
179          if (this.geom && this.material) {
180            this.geom.mesh.materialOverride = this.material as scene3d.ShaderMaterial;
181          }
182        }).id('material_override')
183
184        Text(this.meshInfo);
185        Text(this.hierarchy);
186        Button('back').onClick(() => {
187          this.backAnimator?.cancel();
188          router.back()
189        }).id('back_shader')
190      }
191      .width('100%')
192    }
193    .height('100%')
194  }
195}
196