从0开始的Oasis Engine学习笔记(四) —— 资源管理与加载

这是我参与更文挑战的第4天,活动详情查看: 更文挑战

在开发中,最常用的就是加载资源,本篇文章就会介绍如果在Oasis中引入资源。我们使用挂载在 Engine 实例中的 resourceManager 管理与加载资源。然后使用load 方法即可传入 url。

我们将介绍Oasis里常见的3种纹理资源加载

什么是纹理

纹理(Texture), 是在 3D 渲染中最常用到的资源。我们在给模型着色时,需要给每个片元设置一个颜色值,这个色值除了直接手动设置,我们还可以选择从纹理中读取纹素来进行着色,来达到更加丰富的美术效果。

值得注意的是,图片、canvas 画布、原始数据、视频等都可以用来当作纹理,Oasis 引擎目前支持所有 WebGL 标准的纹理。

2D纹理

    const textureResource = {
       type: AssetType.Texture2D,
       url: '图片url'
    }
    
    // 通过 ResourceManager 来加载 2D 纹理
    engine.resourceManager.load<Texture2D>(textureResource)
    .then((cubeMap: Texture2D) => {
    
      // 创建一个精灵实体
      const spriteEntity = rootEntity.createChild('sprite')
      const spriteRenderer = spriteEntity.addComponent(SpriteRenderer)
      spriteEntity.transform.position = new Vector3(-5, 0)
      
      // 通过new Sprite将纹理加载到精灵实体上
      const sprite = new Sprite(engine, texture)
      spriteRenderer.sprite = sprite
    })
复制代码
成功加载精灵纹理效果

image.png

3D纹理

3D纹理的加载需要6个面的图片,而且立方纹理必须保证每张2D纹理的分辨率相等,即每张2D纹理的宽高必须一致。

    const cubeTextureResource ={
       type: AssetType.TextureCube,
       urls:[
          "px - right 图片 url",
          "nx - left 图片 url",
          "py - top 图片 url",
          "ny - bottom 图片 url",
          "pz - front 图片 url",
          "nz - back 图片 url",
       ]
    }
    
   // 通过 ResourceManager 来加载 3D 纹理
  engine.resourceManager.load<TextureCubeMap>(cubeTextureResource)
    .then((cubeMap: TextureCubeMap) => {
    
      // 创建一个立方体实体
      const cubeEntity = rootEntity.createChild('cube')
      const cube = cubeEntity.addComponent(MeshRenderer)
      cube.mesh = PrimitiveMesh.createCuboid(engine, 5, 5, 5)
      
      // 通过创建PBRMaterial获取材质
      const material = new PBRMaterial(engine)
      // 通过PBRMaterial下的reflectionTexture方法,将3D纹理资源加载到材质上
      material.reflectionTexture = cubeMap
      // 设置实体材质
      cube.setMaterial(material)
    })
复制代码
成功加载3D纹理效果

image.png

天坑点

在加载3D纹理的时候需要注意

image.png

    const material = new PBRMaterial(engine);
    const texture = 生成纹理(); // 上文所示,不再赘述

    material.baseColorTexture = texture;
复制代码

如上,官网的教程上使用 baseColorTexture 方法加载纹理资源,但在实际的应用中发现,该方法应该已经被废弃

image.png

当学习Oasis Engine到这里,我深刻的明白确实上了条贼船,版本跟新后,接口改动,教程都不用改一下的吗?

image.png

在放弃的边缘徘徊后,我还是决定将这条贼船开下去

在Vs Code的代码提示下,发现PBRMaterial下有一个的方法 reflectionTexture ,它的类型为 TextureCubeMap

image.png

正确方法

    const material = new PBRMaterial(engine)
    const texture = 生成纹理()
    
    material.reflectionTexture = texture
复制代码

在Oasis的官网里面的教程部分,很有可能会遇到未能及时更新的情况,对于API使用建议到 Oasis Engine 的api里查找

天空盒纹理

天空盒在上一章VR实现里有讲解

天空盒需要的资源和3D纹理类似

image.png
官网的纹理教程中此处为老版接口,ASkyBox 这个类在新版中已经删除。

如下,天空盒纹理正确加载方法

image.png

  engine.resourceManager.load<TextureCubeMap>(cubeTextureResource)
    .then((cubeMap: TextureCubeMap) => {
      background.mode = BackgroundMode.Sky
      const skyMaterial = (background.sky.material = new SkyBoxMaterial(engine))
      skyMaterial.textureCubeMap = cubeMap
      background.sky.mesh = PrimitiveMesh.createCuboid(engine, 2, 2, 2)
    })
复制代码

完整代码

import {
  Camera,
  WebGLEngine,
  Vector3,
  AssetType,
  Texture2D,
  SpriteRenderer,
  Sprite,
  TextureCubeMap,
  MeshRenderer,
  PrimitiveMesh,
  PBRMaterial,
  DirectLight,
  Color,
  BackgroundMode,
  SkyBoxMaterial
} from 'oasis-engine'
import { OrbitControl } from '@oasis-engine/controls'

export function createOasis (): void {
  // 初始化Engine
  const engine = new WebGLEngine('canvas')
  engine.canvas.resizeByClientSize()

  // 获取场景根实体
  const scene = engine.sceneManager.activeScene
  const { background } = scene
  const rootEntity = scene.createRootEntity('root')

  // 创建一个相机实体
  const cameraEntity = rootEntity.createChild('camera_entity')
  cameraEntity.transform.setPosition(0, 0, 10)
  cameraEntity.addComponent(Camera)
  cameraEntity.addComponent(OrbitControl)
  
  // 创建一个光实体
  const lightEntity = rootEntity.createChild('light')
  const directLight = lightEntity.addComponent(DirectLight)
  directLight.color = new Color(1.0, 1.0, 1.0)
  directLight.intensity = 0.5

  // 定义3d资源
  const cubeTextureResource = {
    type: AssetType.TextureCube,
    urls: [
      require('../assets/px.png'),
      require('../assets/nx.png'),
      require('../assets/py.png'),
      require('../assets/ny.png'),
      require('../assets/pz.png'),
      require('../assets/nz.png')
    ]
  }

  // 加载3D资源
  engine.resourceManager.load<TextureCubeMap>(cubeTextureResource)
    .then((cubeMap: TextureCubeMap) => {
      const cubeEntity = rootEntity.createChild('cube')
      const cube = cubeEntity.addComponent(MeshRenderer)
      cube.mesh = PrimitiveMesh.createCuboid(engine, 4, 4, 4)
      const material = new PBRMaterial(engine)
      material.reflectionTexture = cubeMap
      cube.setMaterial(material)
    })
    
  // 加载天空盒
  engine.resourceManager.load<TextureCubeMap>(cubeTextureResource)
    .then((cubeMap: TextureCubeMap) => {
      background.mode = BackgroundMode.Sky
      const skyMaterial = (background.sky.material = new SkyBoxMaterial(engine))
      skyMaterial.textureCubeMap = cubeMap
      background.sky.mesh = PrimitiveMesh.createCuboid(engine, 2, 2, 2)
    })
    
  // 加载2D资源
  engine.resourceManager
    .load<Texture2D>({
      urls: [
        require('../assets/i1.png')
      ],
      type: AssetType.Texture2D
    })
    .then((texture: Texture2D) => {
      const spriteEntity = rootEntity.createChild('sprite')
      const spriteRenderer = spriteEntity.addComponent(SpriteRenderer)
      const sprite = new Sprite(engine, texture)
      spriteRenderer.sprite = sprite
      spriteEntity.transform.position = new Vector3(-5, 0)
    })

  // 启动引擎
  engine.run()
}
复制代码
完成效果

image.png

End

image.gif

respect by myself

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享