这是我参与更文挑战的第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
})
复制代码
成功加载精灵纹理效果
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纹理效果
天坑点
在加载3D纹理的时候需要注意
const material = new PBRMaterial(engine);
const texture = 生成纹理(); // 上文所示,不再赘述
material.baseColorTexture = texture;
复制代码
如上,官网的教程上使用 baseColorTexture 方法加载纹理资源,但在实际的应用中发现,该方法应该已经被废弃
当学习Oasis Engine到这里,我深刻的明白确实上了条贼船,版本跟新后,接口改动,教程都不用改一下的吗?
在放弃的边缘徘徊后,我还是决定将这条贼船开下去
在Vs Code的代码提示下,发现PBRMaterial下有一个的方法 reflectionTexture ,它的类型为 TextureCubeMap
正确方法
const material = new PBRMaterial(engine)
const texture = 生成纹理()
material.reflectionTexture = texture
复制代码
在Oasis的官网里面的教程部分,很有可能会遇到未能及时更新的情况,对于API使用建议到 Oasis Engine 的api里查找
天空盒纹理
天空盒在上一章VR实现里有讲解
天空盒需要的资源和3D纹理类似
官网的纹理教程中此处为老版接口,ASkyBox 这个类在新版中已经删除。
如下,天空盒纹理正确加载方法
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()
}
复制代码
完成效果
End
respect by myself